From 8ee225744f109b19e7d2412cbc50d4586991d8cf Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 10 Jul 2020 21:14:06 -0700 Subject: [PATCH 001/771] [lldb/Test] Fix missing yaml2obj in Xcode standalone build. Rather than trying to find the yaml2obj from dotest we should pass it in like we do for dsymutil and FileCheck. --- .../Python/lldbsuite/test/configuration.py | 10 ++++++++++ lldb/packages/Python/lldbsuite/test/dotest.py | 12 +++++++---- .../Python/lldbsuite/test/dotest_args.py | 2 +- .../Python/lldbsuite/test/lldbtest.py | 20 ++++--------------- lldb/test/API/CMakeLists.txt | 4 ++++ lldb/test/API/lit.cfg.py | 3 +++ lldb/test/API/lit.site.cfg.py.in | 1 + lldb/utils/lldb-dotest/CMakeLists.txt | 5 +++++ lldb/utils/lldb-dotest/lldb-dotest.in | 2 ++ 9 files changed, 38 insertions(+), 21 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/configuration.py b/lldb/packages/Python/lldbsuite/test/configuration.py index f05152253c75f..ca27864463002 100644 --- a/lldb/packages/Python/lldbsuite/test/configuration.py +++ b/lldb/packages/Python/lldbsuite/test/configuration.py @@ -57,6 +57,9 @@ # Path to the FileCheck testing tool. Not optional. filecheck = None +# Path to the yaml2obj tool. Not optional. +yaml2obj = None + # The arch might dictate some specific CFLAGS to be passed to the toolchain to build # the inferior programs. The global variable cflags_extras provides a hook to do # just that. @@ -163,6 +166,13 @@ def get_filecheck_path(): if filecheck and os.path.lexists(filecheck): return filecheck +def get_yaml2obj_path(): + """ + Get the path to the yaml2obj tool. + """ + if yaml2obj and os.path.lexists(yaml2obj): + return yaml2obj + def is_reproducer_replay(): """ Returns true when dotest is being replayed from a reproducer. Never use diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index f9975b27c4759..8238168d0fb6d 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -272,13 +272,17 @@ def parseOptionsAndInitTestdirs(): configuration.dsymutil = seven.get_command_output( 'xcrun -find -toolchain default dsymutil') + + # The lldb-dotest script produced by the CMake build passes in a path to a + # working FileCheck and yaml2obj binary. So does one specific Xcode + # project target. However, when invoking dotest.py directly, a valid + # --filecheck and --yaml2obj option needs to be given. if args.filecheck: - # The lldb-dotest script produced by the CMake build passes in a path - # to a working FileCheck binary. So does one specific Xcode project - # target. However, when invoking dotest.py directly, a valid --filecheck - # option needs to be given. configuration.filecheck = os.path.abspath(args.filecheck) + if args.yaml2obj: + configuration.yaml2obj = os.path.abspath(args.yaml2obj) + if not configuration.get_filecheck_path(): logging.warning('No valid FileCheck executable; some tests may fail...') logging.warning('(Double-check the --filecheck argument to dotest.py)') diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py index ff2ac5a47ea50..d6f59efdf28b4 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest_args.py +++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py @@ -51,7 +51,7 @@ def create_parser(): suggestions: do not lump the "-A arch1 -A arch2" together such that the -E option applies to only one of the architectures''')) group.add_argument('--dsymutil', metavar='dsymutil', dest='dsymutil', help=textwrap.dedent('Specify which dsymutil to use.')) - + group.add_argument('--yaml2obj', metavar='yaml2obj', dest='yaml2obj', help=textwrap.dedent('Specify which yaml2obj binary to use.')) group.add_argument('--filecheck', metavar='filecheck', dest='filecheck', help=textwrap.dedent('Specify which FileCheck binary to use.')) # Test filtering options diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index ddb79de0ab32f..29561d4794beb 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -1633,20 +1633,6 @@ def findBuiltClang(self): return os.environ["CC"] - def findYaml2obj(self): - """ - Get the path to the yaml2obj executable, which can be used to create - test object files from easy to write yaml instructions. - - Throws an Exception if the executable cannot be found. - """ - # Tries to find yaml2obj at the same folder as clang - clang_dir = os.path.dirname(self.findBuiltClang()) - path = distutils.spawn.find_executable("yaml2obj", clang_dir) - if path is not None: - return path - raise Exception("yaml2obj executable not found") - def yaml2obj(self, yaml_path, obj_path): """ @@ -1654,8 +1640,10 @@ def yaml2obj(self, yaml_path, obj_path): Throws subprocess.CalledProcessError if the object could not be created. """ - yaml2obj = self.findYaml2obj() - command = [yaml2obj, "-o=%s" % obj_path, yaml_path] + yaml2obj_bin = configuration.get_yaml2obj_path() + if not yaml2obj_bin: + self.assertTrue(False, "No valid FileCheck executable specified") + command = [yaml2obj_bin, "-o=%s" % obj_path, yaml_path] system([command]) def getBuildFlags( diff --git a/lldb/test/API/CMakeLists.txt b/lldb/test/API/CMakeLists.txt index 9aad9fc750cae..34f3522c8dfec 100644 --- a/lldb/test/API/CMakeLists.txt +++ b/lldb/test/API/CMakeLists.txt @@ -49,6 +49,7 @@ set(LLDB_DEFAULT_TEST_EXECUTABLE "${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb${CMAKE_EXEC # Set the paths to default llvm tools. set(LLDB_DEFAULT_TEST_DSYMUTIL "${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/dsymutil${CMAKE_EXECUTABLE_SUFFIX}") set(LLDB_DEFAULT_TEST_FILECHECK "${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/FileCheck${CMAKE_EXECUTABLE_SUFFIX}") +set(LLDB_DEFAULT_TEST_YAML2OBJ "${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/yaml2obj${CMAKE_EXECUTABLE_SUFFIX}") if (TARGET clang) set(LLDB_DEFAULT_TEST_COMPILER "${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}") @@ -60,6 +61,7 @@ set(LLDB_TEST_EXECUTABLE "${LLDB_DEFAULT_TEST_EXECUTABLE}" CACHE PATH "lldb exec set(LLDB_TEST_COMPILER "${LLDB_DEFAULT_TEST_COMPILER}" CACHE PATH "C Compiler to use for building LLDB test inferiors") set(LLDB_TEST_DSYMUTIL "${LLDB_DEFAULT_TEST_DSYMUTIL}" CACHE PATH "dsymutil used for generating dSYM bundles") set(LLDB_TEST_FILECHECK "${LLDB_DEFAULT_TEST_FILECHECK}" CACHE PATH "FileCheck used for testing purposes") +set(LLDB_TEST_YAML2OBJ "${LLDB_DEFAULT_TEST_YAML2OBJ}" CACHE PATH "yaml2obj used for testing purposes") if ("${LLDB_TEST_COMPILER}" STREQUAL "") message(FATAL_ERROR "LLDB test compiler not specified. Tests will not run.") @@ -145,6 +147,7 @@ if(LLDB_BUILT_STANDALONE) string(REPLACE ${LLVM_RUNTIME_OUTPUT_INTDIR} ${config_runtime_output_dir} LLDB_TEST_COMPILER "${LLDB_TEST_COMPILER}") string(REPLACE ${LLVM_RUNTIME_OUTPUT_INTDIR} ${config_runtime_output_dir} LLDB_TEST_DSYMUTIL "${LLDB_TEST_DSYMUTIL}") string(REPLACE ${LLVM_RUNTIME_OUTPUT_INTDIR} ${config_runtime_output_dir} LLDB_TEST_FILECHECK "${LLDB_TEST_FILECHECK}") + string(REPLACE ${LLVM_RUNTIME_OUTPUT_INTDIR} ${config_runtime_output_dir} LLDB_TEST_YAML2OBJ "${LLDB_TEST_YAML2OBJ}") # Remaining ones must be paths to the provided LLVM build-tree. if(LLVM_CONFIGURATION_TYPES) @@ -172,6 +175,7 @@ string(REPLACE ${CMAKE_CFG_INTDIR} ${dotest_args_replacement} LLDB_TEST_EXECUTAB string(REPLACE ${CMAKE_CFG_INTDIR} ${dotest_args_replacement} LLDB_TEST_COMPILER "${LLDB_TEST_COMPILER}") string(REPLACE ${CMAKE_CFG_INTDIR} ${dotest_args_replacement} LLDB_TEST_DSYMUTIL "${LLDB_TEST_DSYMUTIL}") string(REPLACE ${CMAKE_CFG_INTDIR} ${dotest_args_replacement} LLDB_TEST_FILECHECK "${LLDB_TEST_FILECHECK}") +string(REPLACE ${CMAKE_CFG_INTDIR} ${dotest_args_replacement} LLDB_TEST_YAML2OBJ "${LLDB_TEST_YAML2OBJ}") # Configure the API test suite. configure_lit_site_cfg( diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py index 632d883e0da9a..57e7509a9f7e5 100644 --- a/lldb/test/API/lit.cfg.py +++ b/lldb/test/API/lit.cfg.py @@ -182,6 +182,9 @@ def find_python_interpreter(): if config.filecheck: dotest_cmd += ['--filecheck', config.filecheck] +if config.yaml2obj: + dotest_cmd += ['--yaml2obj', config.yaml2obj] + if config.lldb_libs_dir: dotest_cmd += ['--lldb-libs-dir', config.lldb_libs_dir] diff --git a/lldb/test/API/lit.site.cfg.py.in b/lldb/test/API/lit.site.cfg.py.in index e97f867b265b8..866dc1675e7cf 100644 --- a/lldb/test/API/lit.site.cfg.py.in +++ b/lldb/test/API/lit.site.cfg.py.in @@ -30,6 +30,7 @@ config.test_arch = '@LLDB_TEST_ARCH@' config.test_compiler = '@LLDB_TEST_COMPILER@' config.dsymutil = '@LLDB_TEST_DSYMUTIL@' config.filecheck = '@LLDB_TEST_FILECHECK@' +config.yaml2obj = '@LLDB_TEST_YAML2OBJ@' # The API tests use their own module caches. config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-api") config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-api") diff --git a/lldb/utils/lldb-dotest/CMakeLists.txt b/lldb/utils/lldb-dotest/CMakeLists.txt index 0278c370f7fe1..0ef60c1427610 100644 --- a/lldb/utils/lldb-dotest/CMakeLists.txt +++ b/lldb/utils/lldb-dotest/CMakeLists.txt @@ -26,6 +26,7 @@ if(LLDB_BUILT_STANDALONE) string(REPLACE ${LLVM_RUNTIME_OUTPUT_INTDIR} ${config_runtime_output_dir} LLDB_TEST_COMPILER_CONFIGURED "${LLDB_TEST_COMPILER}") string(REPLACE ${LLVM_RUNTIME_OUTPUT_INTDIR} ${config_runtime_output_dir} LLDB_TEST_DSYMUTIL_CONFIGURED "${LLDB_TEST_DSYMUTIL}") string(REPLACE ${LLVM_RUNTIME_OUTPUT_INTDIR} ${config_runtime_output_dir} LLDB_TEST_FILECHECK_CONFIGURED "${LLDB_TEST_FILECHECK}") + string(REPLACE ${LLVM_RUNTIME_OUTPUT_INTDIR} ${config_runtime_output_dir} LLDB_TEST_YAML2OBJ_CONFIGURED "${LLDB_TEST_YAML2OBJ}") # Remaining ones must be paths to the provided LLVM build-tree. if(${config_type} IN_LIST LLVM_CONFIGURATION_TYPES) @@ -37,6 +38,7 @@ if(LLDB_BUILT_STANDALONE) string(REPLACE ${CMAKE_CFG_INTDIR} ${config_type} LLDB_TEST_COMPILER_CONFIGURED "${LLDB_TEST_COMPILER}") string(REPLACE ${CMAKE_CFG_INTDIR} ${config_type} LLDB_TEST_DSYMUTIL_CONFIGURED "${LLDB_TEST_DSYMUTIL}") string(REPLACE ${CMAKE_CFG_INTDIR} ${config_type} LLDB_TEST_FILECHECK_CONFIGURED "${LLDB_TEST_FILECHECK}") + string(REPLACE ${CMAKE_CFG_INTDIR} ${config_type} LLDB_TEST_YAML2OBJ_CONFIGURED "${LLDB_TEST_YAML2OBJ}") string(REPLACE ${CMAKE_CFG_INTDIR} ${config_type} LLDB_LIBS_DIR_CONFIGURED "${LLDB_LIBS_DIR}") else() # Single-configuration generator like Ninja. @@ -47,6 +49,7 @@ if(LLDB_BUILT_STANDALONE) string(REPLACE ${CMAKE_CFG_INTDIR} "." LLDB_TEST_COMPILER_CONFIGURED "${LLDB_TEST_COMPILER}") string(REPLACE ${CMAKE_CFG_INTDIR} "." LLDB_TEST_DSYMUTIL_CONFIGURED "${LLDB_TEST_DSYMUTIL}") string(REPLACE ${CMAKE_CFG_INTDIR} "." LLDB_TEST_FILECHECK_CONFIGURED "${LLDB_TEST_FILECHECK}") + string(REPLACE ${CMAKE_CFG_INTDIR} "." LLDB_TEST_YAML2OBJ_CONFIGURED "${LLDB_TEST_YAML2OBJ_CONFIGURED}") string(REPLACE ${CMAKE_CFG_INTDIR} "." LLDB_LIBS_DIR_CONFIGURED "${LLDB_LIBS_DIR}") endif() @@ -65,6 +68,7 @@ elseif(NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TEST_COMPILER_CONFIGURED "${LLDB_TEST_COMPILER}") string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TEST_DSYMUTIL_CONFIGURED "${LLDB_TEST_DSYMUTIL}") string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TEST_FILECHECK_CONFIGURED "${LLDB_TEST_FILECHECK}") + string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TEST_YAML2OBJ_CONFIGURED "${LLDB_TEST_YAML2OBJ}") string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_LIBS_DIR_CONFIGURED "${LLDB_LIBS_DIR}") configure_file( @@ -80,6 +84,7 @@ else() set(LLDB_TEST_COMPILER_CONFIGURED "${LLDB_TEST_COMPILER}") set(LLDB_TEST_DSYMUTIL_CONFIGURED "${LLDB_TEST_DSYMUTIL}") set(LLDB_TEST_FILECHECK_CONFIGURED "${LLDB_TEST_FILECHECK}") + set(LLDB_TEST_YAML2OBJ_CONFIGURED "${LLDB_TEST_YAML2OBJ}") set(LLDB_LIBS_DIR_CONFIGURED "${LLDB_LIBS_DIR}") configure_file( diff --git a/lldb/utils/lldb-dotest/lldb-dotest.in b/lldb/utils/lldb-dotest/lldb-dotest.in index 36d5fd38cc6d5..ee0ea6dff748c 100755 --- a/lldb/utils/lldb-dotest/lldb-dotest.in +++ b/lldb/utils/lldb-dotest/lldb-dotest.in @@ -10,6 +10,7 @@ executable = '@LLDB_TEST_EXECUTABLE_CONFIGURED@' compiler = '@LLDB_TEST_COMPILER_CONFIGURED@' dsymutil = '@LLDB_TEST_DSYMUTIL_CONFIGURED@' filecheck = '@LLDB_TEST_FILECHECK_CONFIGURED@' +yaml2obj = '@LLDB_TEST_YAML2OBJ_CONFIGURED@' lldb_libs_dir = "@LLDB_LIBS_DIR_CONFIGURED@" lldb_build_intel_pt = "@LLDB_BUILD_INTEL_PT@" @@ -24,6 +25,7 @@ if __name__ == '__main__': cmd.extend(['--executable', executable]) cmd.extend(['--compiler', compiler]) cmd.extend(['--dsymutil', dsymutil]) + cmd.extend(['--yaml2obj', yaml2obj]) cmd.extend(['--filecheck', filecheck]) cmd.extend(['--lldb-libs-dir', lldb_libs_dir]) if lldb_build_intel_pt == "1": From b5667d00e0447747419a783697b84a37f59ce055 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Fri, 10 Jul 2020 16:45:02 -0500 Subject: [PATCH 002/771] [OpenMP][CUDA] Fix std::complex in GPU regions The old way worked to some degree for C++-mode but in C mode we actually tried to introduce variants of macros (e.g., isinf). To make both modes work reliably we get rid of those extra variants and directly use NVIDIA intrinsics in the complex implementation. While this has to be revisited as we add other GPU targets which want to reuse the code, it should be fine for now. Reviewed By: tra, JonChesterfield, yaxunl Differential Revision: https://reviews.llvm.org/D83591 --- .../Headers/__clang_cuda_complex_builtins.h | 52 +++++++++---------- clang/lib/Headers/__clang_cuda_math.h | 10 ---- .../test/Headers/nvptx_device_math_complex.c | 31 +++++++++-- .../Headers/nvptx_device_math_complex.cpp | 31 +++++++++-- 4 files changed, 76 insertions(+), 48 deletions(-) diff --git a/clang/lib/Headers/__clang_cuda_complex_builtins.h b/clang/lib/Headers/__clang_cuda_complex_builtins.h index c48c754ed1a4b..8c10ff6b461fd 100644 --- a/clang/lib/Headers/__clang_cuda_complex_builtins.h +++ b/clang/lib/Headers/__clang_cuda_complex_builtins.h @@ -23,20 +23,16 @@ #define __DEVICE__ __device__ inline #endif -// Make the algorithms available for C and C++ by selecting the right functions. -#if defined(__cplusplus) -// TODO: In OpenMP mode we cannot overload isinf/isnan/isfinite the way we -// overload all other math functions because old math system headers and not -// always conformant and return an integer instead of a boolean. Until that has -// been addressed we need to work around it. For now, we substituate with the -// calls we would have used to implement those three functions. Note that we -// could use the C alternatives as well. -#define _ISNANd ::__isnan -#define _ISNANf ::__isnanf -#define _ISINFd ::__isinf -#define _ISINFf ::__isinff -#define _ISFINITEd ::__isfinited -#define _ISFINITEf ::__finitef +// To make the algorithms available for C and C++ in CUDA and OpenMP we select +// different but equivalent function versions. TODO: For OpenMP we currently +// select the native builtins as the overload support for templates is lacking. +#if !defined(_OPENMP) +#define _ISNANd std::isnan +#define _ISNANf std::isnan +#define _ISINFd std::isinf +#define _ISINFf std::isinf +#define _ISFINITEd std::isfinite +#define _ISFINITEf std::isfinite #define _COPYSIGNd std::copysign #define _COPYSIGNf std::copysign #define _SCALBNd std::scalbn @@ -46,20 +42,20 @@ #define _LOGBd std::logb #define _LOGBf std::logb #else -#define _ISNANd isnan -#define _ISNANf isnanf -#define _ISINFd isinf -#define _ISINFf isinff -#define _ISFINITEd isfinite -#define _ISFINITEf isfinitef -#define _COPYSIGNd copysign -#define _COPYSIGNf copysignf -#define _SCALBNd scalbn -#define _SCALBNf scalbnf -#define _ABSd abs -#define _ABSf absf -#define _LOGBd logb -#define _LOGBf logbf +#define _ISNANd __nv_isnand +#define _ISNANf __nv_isnanf +#define _ISINFd __nv_isinfd +#define _ISINFf __nv_isinff +#define _ISFINITEd __nv_isfinited +#define _ISFINITEf __nv_finitef +#define _COPYSIGNd __nv_copysign +#define _COPYSIGNf __nv_copysignf +#define _SCALBNd __nv_scalbn +#define _SCALBNf __nv_scalbnf +#define _ABSd __nv_fabs +#define _ABSf __nv_fabsf +#define _LOGBd __nv_logb +#define _LOGBf __nv_logbf #endif #if defined(__cplusplus) diff --git a/clang/lib/Headers/__clang_cuda_math.h b/clang/lib/Headers/__clang_cuda_math.h index 2e8e6ae71d9cf..332e616702acf 100644 --- a/clang/lib/Headers/__clang_cuda_math.h +++ b/clang/lib/Headers/__clang_cuda_math.h @@ -340,16 +340,6 @@ __DEVICE__ float y1f(float __a) { return __nv_y1f(__a); } __DEVICE__ double yn(int __a, double __b) { return __nv_yn(__a, __b); } __DEVICE__ float ynf(int __a, float __b) { return __nv_ynf(__a, __b); } -// In C++ mode OpenMP takes the system versions of these because some math -// headers provide the wrong return type. This cannot happen in C and we can and -// want to use the specialized versions right away. -#if defined(_OPENMP) && !defined(__cplusplus) -__DEVICE__ int isinff(float __x) { return __nv_isinff(__x); } -__DEVICE__ int isinf(double __x) { return __nv_isinfd(__x); } -__DEVICE__ int isnanf(float __x) { return __nv_isnanf(__x); } -__DEVICE__ int isnan(double __x) { return __nv_isnand(__x); } -#endif - #pragma pop_macro("__DEVICE__") #pragma pop_macro("__DEVICE_VOID__") #pragma pop_macro("__FAST_OR_SLOW") diff --git a/clang/test/Headers/nvptx_device_math_complex.c b/clang/test/Headers/nvptx_device_math_complex.c index 0e212592dd2ba..6e3e8bffbd24e 100644 --- a/clang/test/Headers/nvptx_device_math_complex.c +++ b/clang/test/Headers/nvptx_device_math_complex.c @@ -11,12 +11,34 @@ #include #endif -// CHECK-DAG: define weak {{.*}} @__mulsc3 -// CHECK-DAG: define weak {{.*}} @__muldc3 -// CHECK-DAG: define weak {{.*}} @__divsc3 -// CHECK-DAG: define weak {{.*}} @__divdc3 +// CHECK: define weak {{.*}} @__muldc3 +// CHECK-DAG: call i32 @__nv_isnand( +// CHECK-DAG: call i32 @__nv_isinfd( +// CHECK-DAG: call double @__nv_copysign( +// CHECK: define weak {{.*}} @__mulsc3 +// CHECK-DAG: call i32 @__nv_isnanf( +// CHECK-DAG: call i32 @__nv_isinff( +// CHECK-DAG: call float @__nv_copysignf( + +// CHECK: define weak {{.*}} @__divdc3 +// CHECK-DAG: call i32 @__nv_isnand( +// CHECK-DAG: call i32 @__nv_isinfd( +// CHECK-DAG: call i32 @__nv_isfinited( +// CHECK-DAG: call double @__nv_copysign( +// CHECK-DAG: call double @__nv_scalbn( +// CHECK-DAG: call double @__nv_fabs( +// CHECK-DAG: call double @__nv_logb( + +// CHECK: define weak {{.*}} @__divsc3 +// CHECK-DAG: call i32 @__nv_isnanf( +// CHECK-DAG: call i32 @__nv_isinff( +// CHECK-DAG: call i32 @__nv_finitef( +// CHECK-DAG: call float @__nv_copysignf( // CHECK-DAG: call float @__nv_scalbnf( +// CHECK-DAG: call float @__nv_fabsf( +// CHECK-DAG: call float @__nv_logbf( + void test_scmplx(float _Complex a) { #pragma omp target { @@ -24,7 +46,6 @@ void test_scmplx(float _Complex a) { } } -// CHECK-DAG: call double @__nv_scalbn( void test_dcmplx(double _Complex a) { #pragma omp target { diff --git a/clang/test/Headers/nvptx_device_math_complex.cpp b/clang/test/Headers/nvptx_device_math_complex.cpp index 58ed24b74b0e4..e4b78deb05d7b 100644 --- a/clang/test/Headers/nvptx_device_math_complex.cpp +++ b/clang/test/Headers/nvptx_device_math_complex.cpp @@ -5,12 +5,34 @@ #include -// CHECK-DAG: define weak {{.*}} @__mulsc3 -// CHECK-DAG: define weak {{.*}} @__muldc3 -// CHECK-DAG: define weak {{.*}} @__divsc3 -// CHECK-DAG: define weak {{.*}} @__divdc3 +// CHECK: define weak {{.*}} @__muldc3 +// CHECK-DAG: call i32 @__nv_isnand( +// CHECK-DAG: call i32 @__nv_isinfd( +// CHECK-DAG: call double @__nv_copysign( +// CHECK: define weak {{.*}} @__mulsc3 +// CHECK-DAG: call i32 @__nv_isnanf( +// CHECK-DAG: call i32 @__nv_isinff( +// CHECK-DAG: call float @__nv_copysignf( + +// CHECK: define weak {{.*}} @__divdc3 +// CHECK-DAG: call i32 @__nv_isnand( +// CHECK-DAG: call i32 @__nv_isinfd( +// CHECK-DAG: call i32 @__nv_isfinited( +// CHECK-DAG: call double @__nv_copysign( +// CHECK-DAG: call double @__nv_scalbn( +// CHECK-DAG: call double @__nv_fabs( +// CHECK-DAG: call double @__nv_logb( + +// CHECK: define weak {{.*}} @__divsc3 +// CHECK-DAG: call i32 @__nv_isnanf( +// CHECK-DAG: call i32 @__nv_isinff( +// CHECK-DAG: call i32 @__nv_finitef( +// CHECK-DAG: call float @__nv_copysignf( // CHECK-DAG: call float @__nv_scalbnf( +// CHECK-DAG: call float @__nv_fabsf( +// CHECK-DAG: call float @__nv_logbf( + void test_scmplx(std::complex a) { #pragma omp target { @@ -18,7 +40,6 @@ void test_scmplx(std::complex a) { } } -// CHECK-DAG: call double @__nv_scalbn( void test_dcmplx(std::complex a) { #pragma omp target { From 256e4d46a67517056d1e45d71c02424db01eff44 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 10 Jul 2020 22:52:04 -0700 Subject: [PATCH 003/771] Fix signed vs unsigned comparison warnings a different way. --- .../MachONormalizedFileBinaryReaderTests.cpp | 20 ++++++++-------- .../MachONormalizedFileYAMLTests.cpp | 24 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/lld/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp b/lld/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp index aad5f8afcfdc3..fbf18a8d9e007 100644 --- a/lld/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp +++ b/lld/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp @@ -75,7 +75,7 @@ TEST(BinaryReaderTest, empty_obj_x86_64) { fromBinary(fileBytes, sizeof(fileBytes), "x86_64"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); EXPECT_TRUE(f->undefinedSymbols.empty()); @@ -106,7 +106,7 @@ TEST(BinaryReaderTest, empty_obj_x86) { fromBinary(fileBytes, sizeof(fileBytes), "i386"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); EXPECT_TRUE(f->undefinedSymbols.empty()); @@ -137,7 +137,7 @@ TEST(BinaryReaderTest, empty_obj_ppc) { fromBinary(fileBytes, sizeof(fileBytes), "ppc"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); EXPECT_TRUE(f->undefinedSymbols.empty()); @@ -168,7 +168,7 @@ TEST(BinaryReaderTest, empty_obj_armv7) { fromBinary(fileBytes, sizeof(fileBytes), "armv7"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); EXPECT_TRUE(f->undefinedSymbols.empty()); @@ -182,7 +182,7 @@ TEST(BinaryReaderTest, empty_obj_x86_64_arm7) { fromBinary(fileBytes, sizeof(fileBytes), "x86_64"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); EXPECT_TRUE(f->undefinedSymbols.empty()); @@ -191,7 +191,7 @@ TEST(BinaryReaderTest, empty_obj_x86_64_arm7) { fromBinary(fileBytes, sizeof(fileBytes), "armv7"); EXPECT_EQ(f2->arch, lld::MachOLinkingContext::arch_armv7); EXPECT_EQ((int)(f2->fileType), MH_OBJECT); - EXPECT_EQ((int)(f2->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f2->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f2->localSymbols.empty()); EXPECT_TRUE(f2->globalSymbols.empty()); EXPECT_TRUE(f2->undefinedSymbols.empty()); @@ -268,7 +268,7 @@ TEST(BinaryReaderTest, hello_obj_x86_64) { EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_EQ(f->sections.size(), 2UL); const Section& text = f->sections[0]; EXPECT_TRUE(text.segmentName.equals("__TEXT")); @@ -393,7 +393,7 @@ TEST(BinaryReaderTest, hello_obj_x86) { EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_EQ(f->sections.size(), 2UL); const Section& text = f->sections[0]; EXPECT_TRUE(text.segmentName.equals("__TEXT")); @@ -525,7 +525,7 @@ TEST(BinaryReaderTest, hello_obj_armv7) { EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_EQ(f->sections.size(), 2UL); const Section& text = f->sections[0]; EXPECT_TRUE(text.segmentName.equals("__TEXT")); @@ -669,7 +669,7 @@ TEST(BinaryReaderTest, hello_obj_ppc) { EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc); EXPECT_EQ((int)(f->fileType), MH_OBJECT); - EXPECT_EQ((int)(f->flags), MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_EQ(f->sections.size(), 2UL); const Section& text = f->sections[0]; EXPECT_TRUE(text.segmentName.equals("__TEXT")); diff --git a/lld/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp b/lld/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp index 6ceb197b4b84a..dbfe3a051811a 100644 --- a/lld/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp +++ b/lld/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp @@ -50,7 +50,7 @@ TEST(ObjectFileYAML, empty_ppc) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_ppc); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)(int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->sections.empty()); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); @@ -66,7 +66,7 @@ TEST(ObjectFileYAML, empty_x86_64) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)(int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->sections.empty()); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); @@ -82,7 +82,7 @@ TEST(ObjectFileYAML, empty_x86) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->sections.empty()); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); @@ -98,7 +98,7 @@ TEST(ObjectFileYAML, empty_armv6) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv6); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->sections.empty()); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); @@ -114,7 +114,7 @@ TEST(ObjectFileYAML, empty_armv7) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->sections.empty()); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); @@ -130,7 +130,7 @@ TEST(ObjectFileYAML, empty_armv7s) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7s); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f->sections.empty()); EXPECT_TRUE(f->localSymbols.empty()); EXPECT_TRUE(f->globalSymbols.empty()); @@ -143,7 +143,7 @@ TEST(ObjectFileYAML, roundTrip) { NormalizedFile f; f.arch = lld::MachOLinkingContext::arch_x86_64; f.fileType = llvm::MachO::MH_OBJECT; - f.flags = llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS; + f.flags = (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS; f.os = lld::MachOLinkingContext::OS::macOSX; toYAML(f, intermediate); } @@ -151,7 +151,7 @@ TEST(ObjectFileYAML, roundTrip) { std::unique_ptr f2 = fromYAML(intermediate); EXPECT_EQ(f2->arch, lld::MachOLinkingContext::arch_x86_64); EXPECT_EQ((int)(f2->fileType), llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f2->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f2->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_TRUE(f2->sections.empty()); EXPECT_TRUE(f2->localSymbols.empty()); EXPECT_TRUE(f2->globalSymbols.empty()); @@ -275,7 +275,7 @@ TEST(ObjectFileYAML, hello_x86_64) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86_64); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_EQ(f->sections.size(), 2UL); const Section& sect1 = f->sections[0]; @@ -405,7 +405,7 @@ TEST(ObjectFileYAML, hello_x86) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_x86); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_EQ(f->sections.size(), 2UL); const Section& sect1 = f->sections[0]; @@ -533,7 +533,7 @@ TEST(ObjectFileYAML, hello_armv6) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv6); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_EQ(f->sections.size(), 2UL); const Section& sect1 = f->sections[0]; @@ -673,7 +673,7 @@ TEST(ObjectFileYAML, hello_armv7) { "...\n"); EXPECT_EQ(f->arch, lld::MachOLinkingContext::arch_armv7); EXPECT_EQ(f->fileType, llvm::MachO::MH_OBJECT); - EXPECT_EQ((int)(f->flags), llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); + EXPECT_EQ((int)(f->flags), (int)llvm::MachO::MH_SUBSECTIONS_VIA_SYMBOLS); EXPECT_EQ(f->sections.size(), 2UL); const Section& sect1 = f->sections[0]; From c98699582a6333bbe76ff7853b4cd6beb45754cf Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Mon, 6 Jul 2020 19:13:37 -0500 Subject: [PATCH 004/771] [OpenMP][NFC] Remove unused (always fixed) arguments There are various runtime calls in the device runtime with unused, or always fixed, arguments. This is bad for all sorts of reasons. Clean up two before as we match them in OpenMPOpt now. Reviewed By: JonChesterfield Differential Revision: https://reviews.llvm.org/D83268 --- clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp | 20 ++++++++----------- clang/test/OpenMP/nvptx_data_sharing.cpp | 4 ++-- clang/test/OpenMP/nvptx_parallel_codegen.cpp | 10 +++++----- clang/test/OpenMP/nvptx_target_codegen.cpp | 2 +- .../OpenMP/nvptx_target_teams_codegen.cpp | 4 ++-- .../nvptx_target_teams_distribute_codegen.cpp | 2 +- .../include/llvm/Frontend/OpenMP/OMPKinds.def | 5 +++++ .../deviceRTLs/common/src/parallel.cu | 9 ++------- openmp/libomptarget/deviceRTLs/interface.h | 6 ++---- 9 files changed, 28 insertions(+), 34 deletions(-) diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp index cabd06bd76e84..cbd443134e7a8 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntimeNVPTX.cpp @@ -38,11 +38,9 @@ enum OpenMPRTLFunctionNVPTX { /// Call to void __kmpc_spmd_kernel_deinit_v2(int16_t RequiresOMPRuntime); OMPRTL_NVPTX__kmpc_spmd_kernel_deinit_v2, /// Call to void __kmpc_kernel_prepare_parallel(void - /// *outlined_function, int16_t - /// IsOMPRuntimeInitialized); + /// *outlined_function); OMPRTL_NVPTX__kmpc_kernel_prepare_parallel, - /// Call to bool __kmpc_kernel_parallel(void **outlined_function, - /// int16_t IsOMPRuntimeInitialized); + /// Call to bool __kmpc_kernel_parallel(void **outlined_function); OMPRTL_NVPTX__kmpc_kernel_parallel, /// Call to void __kmpc_kernel_end_parallel(); OMPRTL_NVPTX__kmpc_kernel_end_parallel, @@ -1466,8 +1464,7 @@ void CGOpenMPRuntimeNVPTX::emitWorkerLoop(CodeGenFunction &CGF, CGF.InitTempAlloca(WorkFn, llvm::Constant::getNullValue(CGF.Int8PtrTy)); // TODO: Optimize runtime initialization and pass in correct value. - llvm::Value *Args[] = {WorkFn.getPointer(), - /*RequiresOMPRuntime=*/Bld.getInt16(1)}; + llvm::Value *Args[] = {WorkFn.getPointer()}; llvm::Value *Ret = CGF.EmitRuntimeCall( createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_parallel), Args); Bld.CreateStore(Bld.CreateZExt(Ret, CGF.Int8Ty), ExecStatus); @@ -1595,17 +1592,16 @@ CGOpenMPRuntimeNVPTX::createNVPTXRuntimeFunction(unsigned Function) { } case OMPRTL_NVPTX__kmpc_kernel_prepare_parallel: { /// Build void __kmpc_kernel_prepare_parallel( - /// void *outlined_function, int16_t IsOMPRuntimeInitialized); - llvm::Type *TypeParams[] = {CGM.Int8PtrTy, CGM.Int16Ty}; + /// void *outlined_function); + llvm::Type *TypeParams[] = {CGM.Int8PtrTy}; auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_kernel_prepare_parallel"); break; } case OMPRTL_NVPTX__kmpc_kernel_parallel: { - /// Build bool __kmpc_kernel_parallel(void **outlined_function, - /// int16_t IsOMPRuntimeInitialized); - llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy, CGM.Int16Ty}; + /// Build bool __kmpc_kernel_parallel(void **outlined_function); + llvm::Type *TypeParams[] = {CGM.Int8PtrPtrTy}; llvm::Type *RetTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy); auto *FnTy = llvm::FunctionType::get(RetTy, TypeParams, /*isVarArg*/ false); @@ -2569,7 +2565,7 @@ void CGOpenMPRuntimeNVPTX::emitNonSPMDParallelCall( llvm::Value *ID = Bld.CreateBitOrPointerCast(WFn, CGM.Int8PtrTy); // Prepare for parallel region. Indicate the outlined function. - llvm::Value *Args[] = {ID, /*RequiresOMPRuntime=*/Bld.getInt16(1)}; + llvm::Value *Args[] = {ID}; CGF.EmitRuntimeCall( createNVPTXRuntimeFunction(OMPRTL_NVPTX__kmpc_kernel_prepare_parallel), Args); diff --git a/clang/test/OpenMP/nvptx_data_sharing.cpp b/clang/test/OpenMP/nvptx_data_sharing.cpp index 2ee6bd2b4701c..1372246c7fc8c 100644 --- a/clang/test/OpenMP/nvptx_data_sharing.cpp +++ b/clang/test/OpenMP/nvptx_data_sharing.cpp @@ -55,7 +55,7 @@ void test_ds(){ // CK1: [[A:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[GLOBALSTACK2]], i32 0, i32 0 // CK1: [[B:%.+]] = getelementptr inbounds %struct._globalized_locals_ty, %struct._globalized_locals_ty* [[GLOBALSTACK2]], i32 0, i32 1 // CK1: store i32 10, i32* [[A]] -// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i16 1) +// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}) // CK1: call void @__kmpc_begin_sharing_variables(i8*** [[SHAREDARGS1]], i64 1) // CK1: [[SHARGSTMP1:%.+]] = load i8**, i8*** [[SHAREDARGS1]] // CK1: [[SHARGSTMP2:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP1]], i64 0 @@ -65,7 +65,7 @@ void test_ds(){ // CK1: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) // CK1: call void @__kmpc_end_sharing_variables() // CK1: store i32 100, i32* [[B]] -// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}, i16 1) +// CK1: call void @__kmpc_kernel_prepare_parallel({{.*}}) // CK1: call void @__kmpc_begin_sharing_variables(i8*** [[SHAREDARGS2]], i64 2) // CK1: [[SHARGSTMP3:%.+]] = load i8**, i8*** [[SHAREDARGS2]] // CK1: [[SHARGSTMP4:%.+]] = getelementptr inbounds i8*, i8** [[SHARGSTMP3]], i64 0 diff --git a/clang/test/OpenMP/nvptx_parallel_codegen.cpp b/clang/test/OpenMP/nvptx_parallel_codegen.cpp index c8b15c8f6e3ba..ad25e0d775d12 100644 --- a/clang/test/OpenMP/nvptx_parallel_codegen.cpp +++ b/clang/test/OpenMP/nvptx_parallel_codegen.cpp @@ -92,7 +92,7 @@ int bar(int n){ // // CHECK: [[AWAIT_WORK]] // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) #[[#CONVERGENT:]] -// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]] +// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]) // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8 // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], @@ -166,13 +166,13 @@ int bar(int n){ // CHECK-DAG: [[MWS:%.+]] = call i32 @llvm.nvvm.read.ptx.sreg.warpsize() // CHECK: [[MTMP1:%.+]] = sub nuw i32 [[MNTH]], [[MWS]] // CHECK: call void @__kmpc_kernel_init(i32 [[MTMP1]] -// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN1]]_wrapper to i8*), +// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN1]]_wrapper to i8*)) // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) // CHECK: call void @__kmpc_serialized_parallel( // CHECK: {{call|invoke}} void [[PARALLEL_FN3:@.+]]( // CHECK: call void @__kmpc_end_serialized_parallel( -// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN2]]_wrapper to i8*), +// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN2]]_wrapper to i8*)) // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) // CHECK-64-DAG: load i32, i32* [[REF_A]] @@ -211,7 +211,7 @@ int bar(int n){ // // CHECK: [[AWAIT_WORK]] // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) -// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], +// CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]) // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8 // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], @@ -291,7 +291,7 @@ int bar(int n){ // CHECK: br i1 [[CMP]], label {{%?}}[[IF_THEN:.+]], label {{%?}}[[IF_ELSE:.+]] // // CHECK: [[IF_THEN]] -// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN4]]_wrapper to i8*), +// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* [[PARALLEL_FN4]]_wrapper to i8*)) // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) // CHECK: br label {{%?}}[[IF_END:.+]] diff --git a/clang/test/OpenMP/nvptx_target_codegen.cpp b/clang/test/OpenMP/nvptx_target_codegen.cpp index 91f31185d8c1a..56f04cb01f0aa 100644 --- a/clang/test/OpenMP/nvptx_target_codegen.cpp +++ b/clang/test/OpenMP/nvptx_target_codegen.cpp @@ -612,7 +612,7 @@ int baz(int f, double &a) { // CHECK: call void @__kmpc_end_serialized_parallel(%struct.ident_t* [[UNKNOWN]], i32 [[GTID]]) // CHECK: br label -// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* @{{.+}} to i8*), i16 1) +// CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* @{{.+}} to i8*)) // CHECK: call void @__kmpc_begin_sharing_variables(i8*** [[SHARED_PTR:%.+]], i{{64|32}} 2) // CHECK: [[SHARED:%.+]] = load i8**, i8*** [[SHARED_PTR]], // CHECK: [[REF:%.+]] = getelementptr inbounds i8*, i8** [[SHARED]], i{{64|32}} 0 diff --git a/clang/test/OpenMP/nvptx_target_teams_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_codegen.cpp index 3ab955fa85080..8ff393f074e4a 100644 --- a/clang/test/OpenMP/nvptx_target_teams_codegen.cpp +++ b/clang/test/OpenMP/nvptx_target_teams_codegen.cpp @@ -68,7 +68,7 @@ int bar(int n){ // // CHECK: [[AWAIT_WORK]] // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) - // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i16 1) + // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]) // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8 // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], @@ -154,7 +154,7 @@ int bar(int n){ // // CHECK: [[AWAIT_WORK]] // CHECK: call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) - // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]], i16 1) + // CHECK: [[KPR:%.+]] = call i1 @__kmpc_kernel_parallel(i8** [[OMP_WORK_FN]]) // CHECK: [[KPRB:%.+]] = zext i1 [[KPR]] to i8 // store i8 [[KPRB]], i8* [[OMP_EXEC_STATUS]], align 1 // CHECK: [[WORK:%.+]] = load i8*, i8** [[OMP_WORK_FN]], diff --git a/clang/test/OpenMP/nvptx_target_teams_distribute_codegen.cpp b/clang/test/OpenMP/nvptx_target_teams_distribute_codegen.cpp index fe294bbddf2b7..4f23f18730cc2 100644 --- a/clang/test/OpenMP/nvptx_target_teams_distribute_codegen.cpp +++ b/clang/test/OpenMP/nvptx_target_teams_distribute_codegen.cpp @@ -88,7 +88,7 @@ int bar(int n){ // CHECK: [[I_ADDR:%.+]] = getelementptr inbounds [[GLOB_TY]], [[GLOB_TY]]* [[RD]], i32 0, i32 0 // // CHECK: call void @__kmpc_for_static_init_4( - // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* @{{.+}} to i8*), i16 1) + // CHECK: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void (i16, i32)* @{{.+}} to i8*)) // CHECK: call void @__kmpc_begin_sharing_variables(i8*** [[SHARED_VARS_PTR:%.+]], i{{64|32}} 1) // CHECK: [[SHARED_VARS_BUF:%.+]] = load i8**, i8*** [[SHARED_VARS_PTR]], // CHECK: [[VARS_BUF:%.+]] = getelementptr inbounds i8*, i8** [[SHARED_VARS_BUF]], i{{64|32}} 0 diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index f286403e657c9..bf799a781ae17 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -584,6 +584,11 @@ __OMP_RTL(__tgt_push_mapper_component, false, Void, VoidPtr, VoidPtr, VoidPtr, __OMP_RTL(__kmpc_task_allow_completion_event, false, VoidPtr, IdentPtr, /* Int */ Int32, /* kmp_task_t */ VoidPtr) +/// Note that device runtime functions (in the following) do not necessarily +/// need attributes as we expect to see the definitions. +__OMP_RTL(__kmpc_kernel_parallel, false, Int1, VoidPtrPtr) +__OMP_RTL(__kmpc_kernel_prepare_parallel, false, Void, VoidPtr) + __OMP_RTL(__last, false, Void, ) #undef __OMP_RTL diff --git a/openmp/libomptarget/deviceRTLs/common/src/parallel.cu b/openmp/libomptarget/deviceRTLs/common/src/parallel.cu index 4f3c3ac0c08a6..20b03e9bab1b4 100644 --- a/openmp/libomptarget/deviceRTLs/common/src/parallel.cu +++ b/openmp/libomptarget/deviceRTLs/common/src/parallel.cu @@ -72,10 +72,8 @@ INLINE static uint16_t determineNumberOfThreads(uint16_t NumThreadsClause, } // This routine is always called by the team master.. -EXTERN void __kmpc_kernel_prepare_parallel(void *WorkFn, - int16_t IsOMPRuntimeInitialized) { +EXTERN void __kmpc_kernel_prepare_parallel(void *WorkFn) { PRINT0(LD_IO, "call to __kmpc_kernel_prepare_parallel\n"); - ASSERT0(LT_FUSSY, IsOMPRuntimeInitialized, "Expected initialized runtime."); omptarget_nvptx_workFn = WorkFn; @@ -120,12 +118,9 @@ EXTERN void __kmpc_kernel_prepare_parallel(void *WorkFn, // returns True if this thread is active, else False. // // Only the worker threads call this routine. -EXTERN bool __kmpc_kernel_parallel(void **WorkFn, - int16_t IsOMPRuntimeInitialized) { +EXTERN bool __kmpc_kernel_parallel(void **WorkFn) { PRINT0(LD_IO | LD_PAR, "call to __kmpc_kernel_parallel\n"); - ASSERT0(LT_FUSSY, IsOMPRuntimeInitialized, "Expected initialized runtime."); - // Work function and arguments for L1 parallel region. *WorkFn = omptarget_nvptx_workFn; diff --git a/openmp/libomptarget/deviceRTLs/interface.h b/openmp/libomptarget/deviceRTLs/interface.h index 39ce73cba957c..4d352bc648fa3 100644 --- a/openmp/libomptarget/deviceRTLs/interface.h +++ b/openmp/libomptarget/deviceRTLs/interface.h @@ -424,10 +424,8 @@ EXTERN void __kmpc_kernel_deinit(int16_t IsOMPRuntimeInitialized); EXTERN void __kmpc_spmd_kernel_init(int ThreadLimit, int16_t RequiresOMPRuntime, int16_t RequiresDataSharing); EXTERN void __kmpc_spmd_kernel_deinit_v2(int16_t RequiresOMPRuntime); -EXTERN void __kmpc_kernel_prepare_parallel(void *WorkFn, - int16_t IsOMPRuntimeInitialized); -EXTERN bool __kmpc_kernel_parallel(void **WorkFn, - int16_t IsOMPRuntimeInitialized); +EXTERN void __kmpc_kernel_prepare_parallel(void *WorkFn); +EXTERN bool __kmpc_kernel_parallel(void **WorkFn); EXTERN void __kmpc_kernel_end_parallel(); EXTERN void __kmpc_data_sharing_init_stack(); From b726c55709a0a5e31a26c8e381544348c5dcd402 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Mon, 6 Jul 2020 19:29:23 -0500 Subject: [PATCH 005/771] [OpenMP][NFC] Fix some typos --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index 0b2e4f24bd178..d7572bf7dc534 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -210,7 +210,7 @@ struct OMPInformationCache : public InformationCache { } // Remove the to-be-deleted indices in reverse order as prior - // modifcations will not modify the smaller indices. + // modifications will not modify the smaller indices. while (!ToBeDeleted.empty()) { unsigned Idx = ToBeDeleted.pop_back_val(); UV[Idx] = UV.back(); @@ -304,7 +304,7 @@ struct OMPInformationCache : public InformationCache { return true; } - // Helper to collect all uses of the decleration in the UsesMap. + // Helper to collect all uses of the declaration in the UsesMap. unsigned collectUses(RuntimeFunctionInfo &RFI, bool CollectStats = true) { unsigned NumUses = 0; if (!RFI.Declaration) @@ -519,7 +519,7 @@ struct OpenMPOpt { return Changed; } - /// Try to eliminiate runtime calls by reusing existing ones. + /// Try to eliminate runtime calls by reusing existing ones. bool deduplicateRuntimeCalls() { bool Changed = false; @@ -615,7 +615,7 @@ struct OpenMPOpt { return Ident; } - /// Try to eliminiate calls of \p RFI in \p F by reusing an existing one or + /// Try to eliminate calls of \p RFI in \p F by reusing an existing one or /// \p ReplVal if given. bool deduplicateRuntimeCalls(Function &F, OMPInformationCache::RuntimeFunctionInfo &RFI, @@ -789,7 +789,7 @@ struct OpenMPOpt { }); } - /// The underyling module. + /// The underlying module. Module &M; /// The SCC we are operating on. From 54bd3751ceebe6eb67804a1ed8be72943817852f Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Mon, 6 Jul 2020 19:30:14 -0500 Subject: [PATCH 006/771] [OpenMP][NFC] Add convenient helper and early exit check --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index d7572bf7dc534..b2e30a4d2b79a 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -161,6 +161,9 @@ struct OMPInformationCache : public InformationCache { /// Clear UsesMap for runtime function. void clearUsesMap() { UsesMap.clear(); } + /// Boolean conversion that is true if the runtime function was found. + operator bool() const { return Declaration; } + /// Return the vector of uses in function \p F. UseVector &getOrCreateUseVector(Function *F) { std::shared_ptr &UV = UsesMap[F]; @@ -411,6 +414,9 @@ struct OpenMPOpt { /// Run all OpenMP optimizations on the underlying SCC/ModuleSlice. bool run() { + if (SCC.empty()) + return false; + bool Changed = false; LLVM_DEBUG(dbgs() << TAG << "Run on SCC with " << SCC.size() From e8039ad4def0c4a2499cfbaba38bcc8ef48dee92 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Mon, 6 Jul 2020 19:19:12 -0500 Subject: [PATCH 007/771] [OpenMP] Identify GPU kernels (aka. OpenMP target regions) We now identify GPU kernels, that is entry points into the GPU code. These kernels (can) correspond to OpenMP target regions. With this patch we identify and on request print them via remarks. Reviewed By: JonChesterfield Differential Revision: https://reviews.llvm.org/D83269 --- llvm/include/llvm/Transforms/IPO/OpenMPOpt.h | 12 ++ llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 127 +++++++++++++----- .../OpenMP/gpu_kernel_detection_remarks.ll | 27 ++++ 3 files changed, 133 insertions(+), 33 deletions(-) create mode 100644 llvm/test/Transforms/OpenMP/gpu_kernel_detection_remarks.ll diff --git a/llvm/include/llvm/Transforms/IPO/OpenMPOpt.h b/llvm/include/llvm/Transforms/IPO/OpenMPOpt.h index 0bd81ea8f5431..d96187b73f9bb 100644 --- a/llvm/include/llvm/Transforms/IPO/OpenMPOpt.h +++ b/llvm/include/llvm/Transforms/IPO/OpenMPOpt.h @@ -17,6 +17,9 @@ namespace llvm { namespace omp { +/// Summary of a kernel (=entry point for target offloading). +using Kernel = Function *; + /// Helper to remember if the module contains OpenMP (runtime calls), to be used /// foremost with containsOpenMP. struct OpenMPInModule { @@ -30,8 +33,17 @@ struct OpenMPInModule { bool isKnown() { return Value != OpenMP::UNKNOWN; } operator bool() { return Value != OpenMP::NOT_FOUND; } + /// Return the known kernels (=GPU entry points) in the module. + SmallPtrSetImpl &getKernels() { return Kernels; } + + /// Identify kernels in the module and populate the Kernels set. + void identifyKernels(Module &M); + private: enum class OpenMP { FOUND, NOT_FOUND, UNKNOWN } Value = OpenMP::UNKNOWN; + + /// Collection of known kernels (=GPU entry points) in the module. + SmallPtrSet Kernels; }; /// Helper to determine if \p M contains OpenMP (runtime calls). diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index b2e30a4d2b79a..f0fc8a6c8c4ac 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -39,6 +39,8 @@ static cl::opt DisableOpenMPOptimizations( static cl::opt PrintICVValues("openmp-print-icv-values", cl::init(false), cl::Hidden); +static cl::opt PrintOpenMPKernels("openmp-print-gpu-kernels", + cl::init(false), cl::Hidden); STATISTIC(NumOpenMPRuntimeCallsDeduplicated, "Number of OpenMP runtime calls deduplicated"); @@ -48,6 +50,8 @@ STATISTIC(NumOpenMPRuntimeFunctionsIdentified, "Number of OpenMP runtime functions identified"); STATISTIC(NumOpenMPRuntimeFunctionUsesIdentified, "Number of OpenMP runtime function uses identified"); +STATISTIC(NumOpenMPTargetRegionKernels, + "Number of OpenMP target region entry points (=kernels) identified"); #if !defined(NDEBUG) static constexpr auto TAG = "[" DEBUG_TYPE "]"; @@ -99,9 +103,10 @@ struct AAICVTracker; struct OMPInformationCache : public InformationCache { OMPInformationCache(Module &M, AnalysisGetter &AG, BumpPtrAllocator &Allocator, SetVector *CGSCC, - SmallPtrSetImpl &ModuleSlice) + SmallPtrSetImpl &ModuleSlice, + SmallPtrSetImpl &Kernels) : InformationCache(M, AG, Allocator, CGSCC), ModuleSlice(ModuleSlice), - OMPBuilder(M) { + OMPBuilder(M), Kernels(Kernels) { OMPBuilder.initialize(); initializeRuntimeFunctions(); initializeInternalControlVars(); @@ -399,6 +404,9 @@ struct OMPInformationCache : public InformationCache { // TODO: We should attach the attributes defined in OMPKinds.def. } + + /// Collection of known kernels (\see Kernel) in the module. + SmallPtrSetImpl &Kernels; }; struct OpenMPOpt { @@ -423,26 +431,10 @@ struct OpenMPOpt { << " functions in a slice with " << OMPInfoCache.ModuleSlice.size() << " functions\n"); - /// Print initial ICV values for testing. - /// FIXME: This should be done from the Attributor once it is added. - if (PrintICVValues) { - InternalControlVar ICVs[] = {ICV_nthreads, ICV_active_levels, ICV_cancel}; - - for (Function *F : OMPInfoCache.ModuleSlice) { - for (auto ICV : ICVs) { - auto ICVInfo = OMPInfoCache.ICVs[ICV]; - auto Remark = [&](OptimizationRemark OR) { - return OR << "OpenMP ICV " << ore::NV("OpenMPICV", ICVInfo.Name) - << " Value: " - << (ICVInfo.InitValue - ? ICVInfo.InitValue->getValue().toString(10, true) - : "IMPLEMENTATION_DEFINED"); - }; - - emitRemarkOnFunction(F, "OpenMPICVTracker", Remark); - } - } - } + if (PrintICVValues) + printICVs(); + if (PrintOpenMPKernels) + printKernels(); Changed |= runAttributor(); @@ -455,6 +447,42 @@ struct OpenMPOpt { return Changed; } + /// Print initial ICV values for testing. + /// FIXME: This should be done from the Attributor once it is added. + void printICVs() const { + InternalControlVar ICVs[] = {ICV_nthreads, ICV_active_levels, ICV_cancel}; + + for (Function *F : OMPInfoCache.ModuleSlice) { + for (auto ICV : ICVs) { + auto ICVInfo = OMPInfoCache.ICVs[ICV]; + auto Remark = [&](OptimizationRemark OR) { + return OR << "OpenMP ICV " << ore::NV("OpenMPICV", ICVInfo.Name) + << " Value: " + << (ICVInfo.InitValue + ? ICVInfo.InitValue->getValue().toString(10, true) + : "IMPLEMENTATION_DEFINED"); + }; + + emitRemarkOnFunction(F, "OpenMPICVTracker", Remark); + } + } + } + + /// Print OpenMP GPU kernels for testing. + void printKernels() const { + for (Function *F : SCC) { + if (!OMPInfoCache.Kernels.count(F)) + continue; + + auto Remark = [&](OptimizationRemark OR) { + return OR << "OpenMP GPU kernel " + << ore::NV("OpenMPGPUKernel", F->getName()) << "\n"; + }; + + emitRemarkOnFunction(F, "OpenMPGPU", Remark); + } + } + /// Return the call if \p U is a callee use in a regular call. If \p RFI is /// given it has to be the callee or a nullptr is returned. static CallInst *getCallIfRegularCall( @@ -775,7 +803,7 @@ struct OpenMPOpt { template > void emitRemark(Instruction *Inst, StringRef RemarkName, - RemarkCallBack &&RemarkCB) { + RemarkCallBack &&RemarkCB) const { Function *F = Inst->getParent()->getParent(); auto &ORE = OREGetter(F); @@ -785,9 +813,10 @@ struct OpenMPOpt { /// Emit a remark on a function. Since only OptimizationRemark is supporting /// this, it can't be made generic. - void emitRemarkOnFunction( - Function *F, StringRef RemarkName, - function_ref &&RemarkCB) { + void + emitRemarkOnFunction(Function *F, StringRef RemarkName, + function_ref + &&RemarkCB) const { auto &ORE = OREGetter(F); ORE.emit([&]() { @@ -1044,7 +1073,8 @@ PreservedAnalyses OpenMPOptPass::run(LazyCallGraph::SCC &C, SetVector Functions(SCC.begin(), SCC.end()); BumpPtrAllocator Allocator; OMPInformationCache InfoCache(*(Functions.back()->getParent()), AG, Allocator, - /*CGSCC*/ &Functions, ModuleSlice); + /*CGSCC*/ &Functions, ModuleSlice, + OMPInModule.getKernels()); Attributor A(Functions, InfoCache, CGUpdater); @@ -1109,9 +1139,9 @@ struct OpenMPOptLegacyPass : public CallGraphSCCPass { AnalysisGetter AG; SetVector Functions(SCC.begin(), SCC.end()); BumpPtrAllocator Allocator; - OMPInformationCache InfoCache(*(Functions.back()->getParent()), AG, - Allocator, - /*CGSCC*/ &Functions, ModuleSlice); + OMPInformationCache InfoCache( + *(Functions.back()->getParent()), AG, Allocator, + /*CGSCC*/ &Functions, ModuleSlice, OMPInModule.getKernels()); Attributor A(Functions, InfoCache, CGUpdater); @@ -1125,14 +1155,45 @@ struct OpenMPOptLegacyPass : public CallGraphSCCPass { } // end anonymous namespace +void OpenMPInModule::identifyKernels(Module &M) { + + NamedMDNode *MD = M.getOrInsertNamedMetadata("nvvm.annotations"); + if (!MD) + return; + + for (auto *Op : MD->operands()) { + if (Op->getNumOperands() < 2) + continue; + MDString *KindID = dyn_cast(Op->getOperand(1)); + if (!KindID || KindID->getString() != "kernel") + continue; + + Function *KernelFn = + mdconst::dyn_extract_or_null(Op->getOperand(0)); + if (!KernelFn) + continue; + + ++NumOpenMPTargetRegionKernels; + + Kernels.insert(KernelFn); + } +} + bool llvm::omp::containsOpenMP(Module &M, OpenMPInModule &OMPInModule) { if (OMPInModule.isKnown()) return OMPInModule; - #define OMP_RTL(_Enum, _Name, ...) \ - if (M.getFunction(_Name)) \ - return OMPInModule = true; + else if (M.getFunction(_Name)) OMPInModule = true; #include "llvm/Frontend/OpenMP/OMPKinds.def" + + // Identify kernels once. TODO: We should split the OMPInformationCache into a + // module and an SCC part. The kernel information, among other things, could + // go into the module part. + if (OMPInModule.isKnown() && OMPInModule) { + OMPInModule.identifyKernels(M); + return true; + } + return OMPInModule = false; } diff --git a/llvm/test/Transforms/OpenMP/gpu_kernel_detection_remarks.ll b/llvm/test/Transforms/OpenMP/gpu_kernel_detection_remarks.ll new file mode 100644 index 0000000000000..ccdf0b981dc2c --- /dev/null +++ b/llvm/test/Transforms/OpenMP/gpu_kernel_detection_remarks.ll @@ -0,0 +1,27 @@ +; RUN: opt -passes=openmpopt -pass-remarks=openmp-opt -openmp-print-gpu-kernels -disable-output < %s 2>&1 | FileCheck %s --implicit-check-not=non_kernel +; RUN: opt -openmpopt -pass-remarks=openmp-opt -openmp-print-gpu-kernels -disable-output < %s 2>&1 | FileCheck %s --implicit-check-not=non_kernel + +; CHECK-DAG: remark: :0:0: OpenMP GPU kernel kernel1 +; CHECK-DAG: remark: :0:0: OpenMP GPU kernel kernel2 + +define void @kernel1() { + ret void +} + +define void @kernel2() { + ret void +} + +define void @non_kernel() { + ret void +} + +; Needed to trigger the openmp-opt pass +declare dso_local void @__kmpc_kernel_prepare_parallel(i8*) + +!nvvm.annotations = !{!2, !0, !1, !3, !1, !2} + +!0 = !{void ()* @kernel1, !"kernel", i32 1} +!1 = !{void ()* @non_kernel, !"non_kernel", i32 1} +!2 = !{null, !"align", i32 1} +!3 = !{void ()* @kernel2, !"kernel", i32 1} From 624d34afff5de099a6f84e678c81055556c3d42d Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Mon, 6 Jul 2020 19:26:01 -0500 Subject: [PATCH 008/771] [OpenMP] Compute a proper module slice for the CGSCCC pass The module slice describes which functions we can analyze and transform while working on an SCC as part of the CGSCC OpenMPOpt pass. So far, we simply restricted it to the SCC. In a follow up we will need to have a bigger scope which is why this patch introduces a proper identification of the module slice. In short, everything that has a transitive reference to a function in the SCC or is transitively referenced by one is fair game. Reviewed By: sstefan1 Differential Revision: https://reviews.llvm.org/D83270 --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 107 +++++++++++++++++++------- 1 file changed, 80 insertions(+), 27 deletions(-) diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index f0fc8a6c8c4ac..38647b5eae688 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -57,6 +57,28 @@ STATISTIC(NumOpenMPTargetRegionKernels, static constexpr auto TAG = "[" DEBUG_TYPE "]"; #endif +/// Apply \p CB to all uses of \p F. If \p LookThroughConstantExprUses is +/// true, constant expression users are not given to \p CB but their uses are +/// traversed transitively. +template +static void foreachUse(Function &F, CBTy CB, + bool LookThroughConstantExprUses = true) { + SmallVector Worklist(make_pointer_range(F.uses())); + + for (unsigned idx = 0; idx < Worklist.size(); ++idx) { + Use &U = *Worklist[idx]; + + // Allow use in constant bitcasts and simply look through them. + if (LookThroughConstantExprUses && isa(U.getUser())) { + for (Use &CEU : cast(U.getUser())->uses()) + Worklist.push_back(&CEU); + continue; + } + + CB(U); + } +} + /// Helper struct to store tracked ICV values at specif instructions. struct ICVValue { Instruction *Inst; @@ -102,11 +124,12 @@ struct AAICVTracker; /// Attributor runs. struct OMPInformationCache : public InformationCache { OMPInformationCache(Module &M, AnalysisGetter &AG, - BumpPtrAllocator &Allocator, SetVector *CGSCC, - SmallPtrSetImpl &ModuleSlice, + BumpPtrAllocator &Allocator, SetVector &CGSCC, SmallPtrSetImpl &Kernels) - : InformationCache(M, AG, Allocator, CGSCC), ModuleSlice(ModuleSlice), - OMPBuilder(M), Kernels(Kernels) { + : InformationCache(M, AG, Allocator, &CGSCC), OMPBuilder(M), + Kernels(Kernels) { + initializeModuleSlice(CGSCC); + OMPBuilder.initialize(); initializeRuntimeFunctions(); initializeInternalControlVars(); @@ -196,20 +219,20 @@ struct OMPInformationCache : public InformationCache { /// Run the callback \p CB on each use and forget the use if the result is /// true. The callback will be fed the function in which the use was /// encountered as second argument. - void foreachUse(function_ref CB) { - for (auto &It : UsesMap) - foreachUse(CB, It.first, It.second.get()); + void foreachUse(SmallVectorImpl &SCC, + function_ref CB) { + for (Function *F : SCC) + foreachUse(CB, F); } /// Run the callback \p CB on each use within the function \p F and forget /// the use if the result is true. - void foreachUse(function_ref CB, Function *F, - UseVector *Uses = nullptr) { + void foreachUse(function_ref CB, Function *F) { SmallVector ToBeDeleted; ToBeDeleted.clear(); unsigned Idx = 0; - UseVector &UV = Uses ? *Uses : getOrCreateUseVector(F); + UseVector &UV = getOrCreateUseVector(F); for (Use *U : UV) { if (CB(*U, *F)) @@ -232,8 +255,45 @@ struct OMPInformationCache : public InformationCache { DenseMap> UsesMap; }; + /// Initialize the ModuleSlice member based on \p SCC. ModuleSlices contains + /// (a subset of) all functions that we can look at during this SCC traversal. + /// This includes functions (transitively) called from the SCC and the + /// (transitive) callers of SCC functions. We also can look at a function if + /// there is a "reference edge", i.a., if the function somehow uses (!=calls) + /// a function in the SCC or a caller of a function in the SCC. + void initializeModuleSlice(SetVector &SCC) { + ModuleSlice.insert(SCC.begin(), SCC.end()); + + SmallPtrSet Seen; + SmallVector Worklist(SCC.begin(), SCC.end()); + while (!Worklist.empty()) { + Function *F = Worklist.pop_back_val(); + ModuleSlice.insert(F); + + for (Instruction &I : instructions(*F)) + if (auto *CB = dyn_cast(&I)) + if (Function *Callee = CB->getCalledFunction()) + if (Seen.insert(Callee).second) + Worklist.push_back(Callee); + } + + Seen.clear(); + Worklist.append(SCC.begin(), SCC.end()); + while (!Worklist.empty()) { + Function *F = Worklist.pop_back_val(); + ModuleSlice.insert(F); + + // Traverse all transitive uses. + foreachUse(*F, [&](Use &U) { + if (auto *UsrI = dyn_cast(U.getUser())) + if (Seen.insert(UsrI->getFunction()).second) + Worklist.push_back(UsrI->getFunction()); + }); + } + } + /// The slice of the module we are allowed to look at. - SmallPtrSetImpl &ModuleSlice; + SmallPtrSet ModuleSlice; /// An OpenMP-IR-Builder instance OpenMPIRBuilder OMPBuilder; @@ -548,7 +608,7 @@ struct OpenMPOpt { return true; }; - RFI.foreachUse(DeleteCallCB); + RFI.foreachUse(SCC, DeleteCallCB); return Changed; } @@ -633,7 +693,7 @@ struct OpenMPOpt { /* GlobalOnly */ true, SingleChoice); return false; }; - RFI.foreachUse(CombineIdentStruct); + RFI.foreachUse(SCC, CombineIdentStruct); if (!Ident || !SingleChoice) { // The IRBuilder uses the insertion block to get to the module, this is @@ -733,7 +793,7 @@ struct OpenMPOpt { Changed = true; return true; }; - RFI.foreachUse(ReplaceAndDeleteCB); + RFI.foreachUse(SCC, ReplaceAndDeleteCB); return Changed; } @@ -776,7 +836,7 @@ struct OpenMPOpt { OMPInformationCache::RuntimeFunctionInfo &GlobThreadNumRFI = OMPInfoCache.RFIs[OMPRTL___kmpc_global_thread_num]; - GlobThreadNumRFI.foreachUse([&](Use &U, Function &F) { + GlobThreadNumRFI.foreachUse(SCC, [&](Use &U, Function &F) { if (CallInst *CI = getCallIfRegularCall(U, &GlobThreadNumRFI)) AddUserArgs(*CI); return false; @@ -938,7 +998,7 @@ struct AAICVTrackerFunction : public AAICVTracker { return true; }; - GetterRFI.foreachUse(ReplaceAndDeleteCB); + GetterRFI.foreachUse(ReplaceAndDeleteCB, getAnchorScope()); return Changed; } @@ -1048,12 +1108,9 @@ PreservedAnalyses OpenMPOptPass::run(LazyCallGraph::SCC &C, if (DisableOpenMPOptimizations) return PreservedAnalyses::all(); - SmallPtrSet ModuleSlice; SmallVector SCC; - for (LazyCallGraph::Node &N : C) { + for (LazyCallGraph::Node &N : C) SCC.push_back(&N.getFunction()); - ModuleSlice.insert(SCC.back()); - } if (SCC.empty()) return PreservedAnalyses::all(); @@ -1073,8 +1130,7 @@ PreservedAnalyses OpenMPOptPass::run(LazyCallGraph::SCC &C, SetVector Functions(SCC.begin(), SCC.end()); BumpPtrAllocator Allocator; OMPInformationCache InfoCache(*(Functions.back()->getParent()), AG, Allocator, - /*CGSCC*/ &Functions, ModuleSlice, - OMPInModule.getKernels()); + /*CGSCC*/ Functions, OMPInModule.getKernels()); Attributor A(Functions, InfoCache, CGUpdater); @@ -1112,14 +1168,11 @@ struct OpenMPOptLegacyPass : public CallGraphSCCPass { if (DisableOpenMPOptimizations || skipSCC(CGSCC)) return false; - SmallPtrSet ModuleSlice; SmallVector SCC; for (CallGraphNode *CGN : CGSCC) if (Function *Fn = CGN->getFunction()) - if (!Fn->isDeclaration()) { + if (!Fn->isDeclaration()) SCC.push_back(Fn); - ModuleSlice.insert(Fn); - } if (SCC.empty()) return false; @@ -1141,7 +1194,7 @@ struct OpenMPOptLegacyPass : public CallGraphSCCPass { BumpPtrAllocator Allocator; OMPInformationCache InfoCache( *(Functions.back()->getParent()), AG, Allocator, - /*CGSCC*/ &Functions, ModuleSlice, OMPInModule.getKernels()); + /*CGSCC*/ Functions, OMPInModule.getKernels()); Attributor A(Functions, InfoCache, CGUpdater); From 5b0581aedc2252481462970503d1085dc27e65eb Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Mon, 6 Jul 2020 19:57:37 -0500 Subject: [PATCH 009/771] [OpenMP] Replace function pointer uses in GPU state machine In non-SPMD mode we create a state machine like code to identify the parallel region the GPU worker threads should execute next. The identification uses the parallel region function pointer as that allows it to work even if the kernel (=target region) and the parallel region are in separate TUs. However, taking the address of a function comes with various downsides. With this patch we will identify the most common situation and replace the function pointer use with a dummy global symbol (for identification purposes only). That means, if the parallel region is only called from a single target region (or kernel), we do not use the function pointer of the parallel region to identify it but a new global symbol. Fixes PR46450. Reviewed By: JonChesterfield Differential Revision: https://reviews.llvm.org/D83271 --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 164 ++++++++++++++++++ ..._state_machine_function_ptr_replacement.ll | 153 ++++++++++++++++ 2 files changed, 317 insertions(+) create mode 100644 llvm/test/Transforms/OpenMP/gpu_state_machine_function_ptr_replacement.ll diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index 38647b5eae688..4df65f81912ba 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -52,6 +52,9 @@ STATISTIC(NumOpenMPRuntimeFunctionUsesIdentified, "Number of OpenMP runtime function uses identified"); STATISTIC(NumOpenMPTargetRegionKernels, "Number of OpenMP target region entry points (=kernels) identified"); +STATISTIC( + NumOpenMPParallelRegionsReplacedInGPUStateMachine, + "Number of OpenMP parallel regions replaced with ID in GPU state machines"); #if !defined(NDEBUG) static constexpr auto TAG = "[" DEBUG_TYPE "]"; @@ -496,6 +499,8 @@ struct OpenMPOpt { if (PrintOpenMPKernels) printKernels(); + Changed |= rewriteDeviceCodeStateMachine(); + Changed |= runAttributor(); // Recollect uses, in case Attributor deleted any. @@ -849,6 +854,31 @@ struct OpenMPOpt { AddUserArgs(*GTIdArgs[u]); } + /// Kernel (=GPU) optimizations and utility functions + /// + ///{{ + + /// Check if \p F is a kernel, hence entry point for target offloading. + bool isKernel(Function &F) { return OMPInfoCache.Kernels.count(&F); } + + /// Cache to remember the unique kernel for a function. + DenseMap> UniqueKernelMap; + + /// Find the unique kernel that will execute \p F, if any. + Kernel getUniqueKernelFor(Function &F); + + /// Find the unique kernel that will execute \p I, if any. + Kernel getUniqueKernelFor(Instruction &I) { + return getUniqueKernelFor(*I.getFunction()); + } + + /// Rewrite the device (=GPU) code state machine create in non-SPMD mode in + /// the cases we can avoid taking the address of a function. + bool rewriteDeviceCodeStateMachine(); + + /// + ///}} + /// Emit a remark generically /// /// This template function can be used to generically emit a remark. The @@ -930,6 +960,140 @@ struct OpenMPOpt { } }; +Kernel OpenMPOpt::getUniqueKernelFor(Function &F) { + if (!OMPInfoCache.ModuleSlice.count(&F)) + return nullptr; + + // Use a scope to keep the lifetime of the CachedKernel short. + { + Optional &CachedKernel = UniqueKernelMap[&F]; + if (CachedKernel) + return *CachedKernel; + + // TODO: We should use an AA to create an (optimistic and callback + // call-aware) call graph. For now we stick to simple patterns that + // are less powerful, basically the worst fixpoint. + if (isKernel(F)) { + CachedKernel = Kernel(&F); + return *CachedKernel; + } + + CachedKernel = nullptr; + if (!F.hasLocalLinkage()) + return nullptr; + } + + auto GetUniqueKernelForUse = [&](const Use &U) -> Kernel { + if (auto *Cmp = dyn_cast(U.getUser())) { + // Allow use in equality comparisons. + if (Cmp->isEquality()) + return getUniqueKernelFor(*Cmp); + return nullptr; + } + if (auto *CB = dyn_cast(U.getUser())) { + // Allow direct calls. + if (CB->isCallee(&U)) + return getUniqueKernelFor(*CB); + // Allow the use in __kmpc_kernel_prepare_parallel calls. + if (Function *Callee = CB->getCalledFunction()) + if (Callee->getName() == "__kmpc_kernel_prepare_parallel") + return getUniqueKernelFor(*CB); + return nullptr; + } + // Disallow every other use. + return nullptr; + }; + + // TODO: In the future we want to track more than just a unique kernel. + SmallPtrSet PotentialKernels; + foreachUse(F, [&](const Use &U) { + PotentialKernels.insert(GetUniqueKernelForUse(U)); + }); + + Kernel K = nullptr; + if (PotentialKernels.size() == 1) + K = *PotentialKernels.begin(); + + // Cache the result. + UniqueKernelMap[&F] = K; + + return K; +} + +bool OpenMPOpt::rewriteDeviceCodeStateMachine() { + constexpr unsigned KMPC_KERNEL_PARALLEL_WORK_FN_PTR_ARG_NO = 0; + + OMPInformationCache::RuntimeFunctionInfo &KernelPrepareParallelRFI = + OMPInfoCache.RFIs[OMPRTL___kmpc_kernel_prepare_parallel]; + + bool Changed = false; + if (!KernelPrepareParallelRFI) + return Changed; + + for (Function *F : SCC) { + + // Check if the function is uses in a __kmpc_kernel_prepare_parallel call at + // all. + bool UnknownUse = false; + unsigned NumDirectCalls = 0; + + SmallVector ToBeReplacedStateMachineUses; + foreachUse(*F, [&](Use &U) { + if (auto *CB = dyn_cast(U.getUser())) + if (CB->isCallee(&U)) { + ++NumDirectCalls; + return; + } + + if (auto *Cmp = dyn_cast(U.getUser())) { + ToBeReplacedStateMachineUses.push_back(&U); + return; + } + if (CallInst *CI = OpenMPOpt::getCallIfRegularCall( + *U.getUser(), &KernelPrepareParallelRFI)) { + ToBeReplacedStateMachineUses.push_back(&U); + return; + } + UnknownUse = true; + }); + + // If this ever hits, we should investigate. + if (UnknownUse || NumDirectCalls != 1) + continue; + + // TODO: This is not a necessary restriction and should be lifted. + if (ToBeReplacedStateMachineUses.size() != 2) + continue; + + // Even if we have __kmpc_kernel_prepare_parallel calls, we (for now) give + // up if the function is not called from a unique kernel. + Kernel K = getUniqueKernelFor(*F); + if (!K) + continue; + + // We now know F is a parallel body function called only from the kernel K. + // We also identified the state machine uses in which we replace the + // function pointer by a new global symbol for identification purposes. This + // ensures only direct calls to the function are left. + + Module &M = *F->getParent(); + Type *Int8Ty = Type::getInt8Ty(M.getContext()); + + auto *ID = new GlobalVariable( + M, Int8Ty, /* isConstant */ true, GlobalValue::PrivateLinkage, + UndefValue::get(Int8Ty), F->getName() + ".ID"); + + for (Use *U : ToBeReplacedStateMachineUses) + U->set(ConstantExpr::getBitCast(ID, U->get()->getType())); + + ++NumOpenMPParallelRegionsReplacedInGPUStateMachine; + + Changed = true; + } + + return Changed; +} + /// Abstract Attribute for tracking ICV values. struct AAICVTracker : public StateWrapper { using Base = StateWrapper; diff --git a/llvm/test/Transforms/OpenMP/gpu_state_machine_function_ptr_replacement.ll b/llvm/test/Transforms/OpenMP/gpu_state_machine_function_ptr_replacement.ll new file mode 100644 index 0000000000000..0a8d7a9d231ae --- /dev/null +++ b/llvm/test/Transforms/OpenMP/gpu_state_machine_function_ptr_replacement.ll @@ -0,0 +1,153 @@ +; RUN: opt -S -passes=openmpopt -pass-remarks=openmp-opt -openmp-print-gpu-kernels < %s | FileCheck %s +; RUN: opt -S -openmpopt -pass-remarks=openmp-opt -openmp-print-gpu-kernels < %s | FileCheck %s + +; C input used for this test: + +; void bar(void) { +; #pragma omp parallel +; { } +; } +; void foo(void) { +; #pragma omp target teams +; { +; #pragma omp parallel +; {} +; bar(); +; #pragma omp parallel +; {} +; } +; } + +; Verify we replace the function pointer uses for the first and last outlined +; region (1 and 3) but not for the middle one (2) because it could be called from +; another kernel. + +; CHECK-DAG: @__omp_outlined__1_wrapper.ID = private constant i8 undef +; CHECK-DAG: @__omp_outlined__3_wrapper.ID = private constant i8 undef + +; CHECK-DAG: icmp eq i8* %5, @__omp_outlined__1_wrapper.ID +; CHECK-DAG: icmp eq i8* %7, @__omp_outlined__3_wrapper.ID + +; CHECK-DAG: call void @__kmpc_kernel_prepare_parallel(i8* @__omp_outlined__1_wrapper.ID) +; CHECK-DAG: call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void ()* @__omp_outlined__2_wrapper to i8*)) +; CHECK-DAG: call void @__kmpc_kernel_prepare_parallel(i8* @__omp_outlined__3_wrapper.ID) + + +%struct.ident_t = type { i32, i32, i32, i32, i8* } + +define internal void @__omp_offloading_35_a1e179_foo_l7_worker() { +entry: + %work_fn = alloca i8*, align 8 + %exec_status = alloca i8, align 1 + store i8* null, i8** %work_fn, align 8 + store i8 0, i8* %exec_status, align 1 + br label %.await.work + +.await.work: ; preds = %.barrier.parallel, %entry + call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) + %0 = call i1 @__kmpc_kernel_parallel(i8** %work_fn) + %1 = zext i1 %0 to i8 + store i8 %1, i8* %exec_status, align 1 + %2 = load i8*, i8** %work_fn, align 8 + %should_terminate = icmp eq i8* %2, null + br i1 %should_terminate, label %.exit, label %.select.workers + +.select.workers: ; preds = %.await.work + %3 = load i8, i8* %exec_status, align 1 + %is_active = icmp ne i8 %3, 0 + br i1 %is_active, label %.execute.parallel, label %.barrier.parallel + +.execute.parallel: ; preds = %.select.workers + %4 = call i32 @__kmpc_global_thread_num(%struct.ident_t* null) + %5 = load i8*, i8** %work_fn, align 8 + %work_match = icmp eq i8* %5, bitcast (void ()* @__omp_outlined__1_wrapper to i8*) + br i1 %work_match, label %.execute.fn, label %.check.next + +.execute.fn: ; preds = %.execute.parallel + call void @__omp_outlined__1_wrapper() + br label %.terminate.parallel + +.check.next: ; preds = %.execute.parallel + %6 = load i8*, i8** %work_fn, align 8 + %work_match1 = icmp eq i8* %6, bitcast (void ()* @__omp_outlined__2_wrapper to i8*) + br i1 %work_match1, label %.execute.fn2, label %.check.next3 + +.execute.fn2: ; preds = %.check.next + call void @__omp_outlined__2_wrapper() + br label %.terminate.parallel + +.check.next3: ; preds = %.check.next + %7 = load i8*, i8** %work_fn, align 8 + %work_match4 = icmp eq i8* %7, bitcast (void ()* @__omp_outlined__3_wrapper to i8*) + br i1 %work_match4, label %.execute.fn5, label %.check.next6 + +.execute.fn5: ; preds = %.check.next3 + call void @__omp_outlined__3_wrapper() + br label %.terminate.parallel + +.check.next6: ; preds = %.check.next3 + %8 = bitcast i8* %2 to void ()* + call void %8() + br label %.terminate.parallel + +.terminate.parallel: ; preds = %.check.next6, %.execute.fn5, %.execute.fn2, %.execute.fn + call void @__kmpc_kernel_end_parallel() + br label %.barrier.parallel + +.barrier.parallel: ; preds = %.terminate.parallel, %.select.workers + call void @__kmpc_barrier_simple_spmd(%struct.ident_t* null, i32 0) + br label %.await.work + +.exit: ; preds = %.await.work + ret void +} + +define weak void @__omp_offloading_35_a1e179_foo_l7() { + call void @__omp_offloading_35_a1e179_foo_l7_worker() + call void @__omp_outlined__() + ret void +} + +define internal void @__omp_outlined__() { + call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void ()* @__omp_outlined__1_wrapper to i8*)) + call void @bar() + call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void ()* @__omp_outlined__3_wrapper to i8*)) + ret void +} + +define internal void @__omp_outlined__1() { + ret void +} + +define internal void @__omp_outlined__1_wrapper() { + call void @__omp_outlined__1() + ret void +} + +define hidden void @bar() { + call void @__kmpc_kernel_prepare_parallel(i8* bitcast (void ()* @__omp_outlined__2_wrapper to i8*)) + ret void +} + +define internal void @__omp_outlined__2_wrapper() { + ret void +} + +define internal void @__omp_outlined__3_wrapper() { + ret void +} + +declare void @__kmpc_kernel_prepare_parallel(i8* %WorkFn) + +declare zeroext i1 @__kmpc_kernel_parallel(i8** nocapture %WorkFn) + +declare void @__kmpc_kernel_end_parallel() + +declare void @__kmpc_barrier_simple_spmd(%struct.ident_t* nocapture readnone %loc_ref, i32 %tid) + +declare i32 @__kmpc_global_thread_num(%struct.ident_t* nocapture readnone) + + +!nvvm.annotations = !{!0} + +!0 = !{void ()* @__omp_offloading_35_a1e179_foo_l7, !"kernel", i32 1} From c44702bcdf8aa829e28399d0d4ac4bfc5ac4fff1 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sat, 11 Jul 2020 07:17:28 +0000 Subject: [PATCH 010/771] Remove unused variable `KMPC_KERNEL_PARALLEL_WORK_FN_PTR_ARG_NO` (NFC) This fixes a compiler warning. --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index 4df65f81912ba..7d93e78357b34 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -1021,8 +1021,6 @@ Kernel OpenMPOpt::getUniqueKernelFor(Function &F) { } bool OpenMPOpt::rewriteDeviceCodeStateMachine() { - constexpr unsigned KMPC_KERNEL_PARALLEL_WORK_FN_PTR_ARG_NO = 0; - OMPInformationCache::RuntimeFunctionInfo &KernelPrepareParallelRFI = OMPInfoCache.RFIs[OMPRTL___kmpc_kernel_prepare_parallel]; From dce6bc18c4e1d086182f9faa3f984912566a3c20 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Sat, 11 Jul 2020 02:36:07 -0500 Subject: [PATCH 011/771] [OpenMP][FIX] remove unused variable and long if-else chain MSVC throws an error if you use "too many" if-else in a row: `Frontend/OpenMP/OMPKinds.def(570): fatal error C1061: compiler limit: blocks nested too deeply` We work around it now... --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index 7d93e78357b34..f25e95466407d 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -1397,9 +1397,17 @@ void OpenMPInModule::identifyKernels(Module &M) { bool llvm::omp::containsOpenMP(Module &M, OpenMPInModule &OMPInModule) { if (OMPInModule.isKnown()) return OMPInModule; + + // MSVC doesn't like long if-else chains for some reason and instead just + // issues an error. Work around it.. + do { #define OMP_RTL(_Enum, _Name, ...) \ - else if (M.getFunction(_Name)) OMPInModule = true; + if (M.getFunction(_Name)) { \ + OMPInModule = true; \ + break; \ + } #include "llvm/Frontend/OpenMP/OMPKinds.def" + } while (false); // Identify kernels once. TODO: We should split the OMPInformationCache into a // module and an SCC part. The kernel information, among other things, could From c3bdc9814d947946bf8e1062f6bf41b7f8813f80 Mon Sep 17 00:00:00 2001 From: Nathan James Date: Sat, 11 Jul 2020 10:10:59 +0100 Subject: [PATCH 012/771] [clang-tidy] Reworked enum options handling(again) Reland b9306fd after fixing the issue causing mac builds to fail unittests. Following on from D77085, I was never happy with the passing a mapping to the option get/store functions. This patch addresses this by using explicit specializations to handle the serializing and deserializing of enum options. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D82188 --- .../clang-tidy/ClangTidyCheck.cpp | 28 ++++--- clang-tools-extra/clang-tidy/ClangTidyCheck.h | 80 +++++++++++-------- .../abseil/StringFindStartswithCheck.cpp | 4 +- .../cppcoreguidelines/InitVariablesCheck.cpp | 4 +- .../ProBoundsConstantArrayIndexCheck.cpp | 1 - .../clang-tidy/modernize/LoopConvertCheck.cpp | 54 +++++++------ .../modernize/MakeSmartPtrCheck.cpp | 4 +- .../clang-tidy/modernize/PassByValueCheck.cpp | 4 +- .../modernize/ReplaceAutoPtrCheck.cpp | 4 +- .../modernize/ReplaceRandomShuffleCheck.cpp | 4 +- .../performance/MoveConstructorInitCheck.cpp | 4 +- .../TypePromotionInMathFnCheck.cpp | 4 +- .../UnnecessaryValueParamCheck.cpp | 4 +- .../readability/IdentifierNamingCheck.cpp | 34 +++++--- .../readability/IdentifierNamingCheck.h | 6 ++ .../clang-tidy/utils/IncludeSorter.cpp | 13 +-- .../clang-tidy/utils/IncludeSorter.h | 9 ++- .../utils/TransformerClangTidyCheck.cpp | 5 +- .../clang-tidy/ClangTidyOptionsTest.cpp | 51 +++++++----- 19 files changed, 174 insertions(+), 143 deletions(-) diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp index 780a3569afdbe..e149978bcdeaf 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @@ -161,11 +161,13 @@ void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options, store(Options, LocalName, llvm::itostr(Value)); } -llvm::Expected ClangTidyCheck::OptionsView::getEnumInt( - StringRef LocalName, ArrayRef> Mapping, - bool CheckGlobal, bool IgnoreCase) { - auto Iter = CheckGlobal ? findPriorityOption(CheckOptions, NamePrefix, LocalName) - : CheckOptions.find((NamePrefix + LocalName).str()); +llvm::Expected +ClangTidyCheck::OptionsView::getEnumInt(StringRef LocalName, + ArrayRef Mapping, + bool CheckGlobal, bool IgnoreCase) { + auto Iter = CheckGlobal + ? findPriorityOption(CheckOptions, NamePrefix, LocalName) + : CheckOptions.find((NamePrefix + LocalName).str()); if (Iter == CheckOptions.end()) return llvm::make_error((NamePrefix + LocalName).str()); @@ -174,19 +176,19 @@ llvm::Expected ClangTidyCheck::OptionsView::getEnumInt( unsigned EditDistance = -1; for (const auto &NameAndEnum : Mapping) { if (IgnoreCase) { - if (Value.equals_lower(NameAndEnum.first)) - return NameAndEnum.second; - } else if (Value.equals(NameAndEnum.first)) { - return NameAndEnum.second; - } else if (Value.equals_lower(NameAndEnum.first)) { - Closest = NameAndEnum.first; + if (Value.equals_lower(NameAndEnum.second)) + return NameAndEnum.first; + } else if (Value.equals(NameAndEnum.second)) { + return NameAndEnum.first; + } else if (Value.equals_lower(NameAndEnum.second)) { + Closest = NameAndEnum.second; EditDistance = 0; continue; } - unsigned Distance = Value.edit_distance(NameAndEnum.first); + unsigned Distance = Value.edit_distance(NameAndEnum.second); if (Distance < EditDistance) { EditDistance = Distance; - Closest = NameAndEnum.first; + Closest = NameAndEnum.second; } } if (EditDistance < 3) diff --git a/clang-tools-extra/clang-tidy/ClangTidyCheck.h b/clang-tools-extra/clang-tidy/ClangTidyCheck.h index dfe01a8aaa30f..3c625ee0cb796 100644 --- a/clang-tools-extra/clang-tidy/ClangTidyCheck.h +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.h @@ -26,6 +26,13 @@ class SourceManager; namespace tidy { +/// This class should be specialized by any enum type that needs to be converted +/// to and from an \ref llvm::StringRef. +template struct OptionEnumMapping { + // Specializations of this struct must implement this function. + static ArrayRef> getEnumMapping() = delete; +}; + template class OptionError : public llvm::ErrorInfo { std::error_code convertToErrorCode() const override { return llvm::inconvertibleErrorCode(); @@ -312,36 +319,38 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { } /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set, - /// it will search the mapping ignoring the case. + /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from the /// ``CheckOptions``. If the corresponding key is not present, returns a /// ``MissingOptionError``. If the key can't be parsed as a ``T`` returns a /// ``UnparseableEnumOptionError``. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, llvm::Expected> - get(StringRef LocalName, ArrayRef> Mapping, - bool IgnoreCase = false) { - if (llvm::Expected ValueOr = getEnumInt( - LocalName, typeEraseMapping(Mapping), false, IgnoreCase)) + get(StringRef LocalName, bool IgnoreCase = false) { + if (llvm::Expected ValueOr = + getEnumInt(LocalName, typeEraseMapping(), false, IgnoreCase)) return static_cast(*ValueOr); else return std::move(ValueOr.takeError()); } /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set, - /// it will search the mapping ignoring the case. + /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from the /// ``CheckOptions``. If the corresponding key is not present or it can't be /// parsed as a ``T``, returns \p Default. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, T> - get(StringRef LocalName, ArrayRef> Mapping, - T Default, bool IgnoreCase = false) { - if (auto ValueOr = get(LocalName, Mapping, IgnoreCase)) + get(StringRef LocalName, T Default, bool IgnoreCase = false) { + if (auto ValueOr = get(LocalName, IgnoreCase)) return *ValueOr; else logErrToStdErr(ValueOr.takeError()); @@ -349,40 +358,41 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { } /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set, - /// it will search the mapping ignoring the case. + /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from local or /// global ``CheckOptions``. Gets local option first. If local is not /// present, falls back to get global option. If global option is not /// present either, returns a ``MissingOptionError``. If the key can't be /// parsed as a ``T`` returns a ``UnparseableEnumOptionError``. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, llvm::Expected> getLocalOrGlobal(StringRef LocalName, - ArrayRef> Mapping, bool IgnoreCase = false) { - if (llvm::Expected ValueOr = getEnumInt( - LocalName, typeEraseMapping(Mapping), true, IgnoreCase)) + if (llvm::Expected ValueOr = + getEnumInt(LocalName, typeEraseMapping(), true, IgnoreCase)) return static_cast(*ValueOr); else return std::move(ValueOr.takeError()); } /// Read a named option from the ``Context`` and parse it as an - /// enum type ``T`` using the \p Mapping provided. If \p IgnoreCase is set, - /// it will search the mapping ignoring the case. + /// enum type ``T``. /// /// Reads the option with the check-local name \p LocalName from local or /// global ``CheckOptions``. Gets local option first. If local is not /// present, falls back to get global option. If global option is not /// present either or it can't be parsed as a ``T``, returns \p Default. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value, T> - getLocalOrGlobal(StringRef LocalName, - ArrayRef> Mapping, T Default, - bool IgnoreCase = false) { - if (auto ValueOr = getLocalOrGlobal(LocalName, Mapping, IgnoreCase)) + getLocalOrGlobal(StringRef LocalName, T Default, bool IgnoreCase = false) { + if (auto ValueOr = getLocalOrGlobal(LocalName, IgnoreCase)) return *ValueOr; else logErrToStdErr(ValueOr.takeError()); @@ -400,21 +410,25 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { int64_t Value) const; /// Stores an option with the check-local name \p LocalName as the string - /// representation of the Enum \p Value using the \p Mapping to \p Options. + /// representation of the Enum \p Value to \p Options. + /// + /// \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to + /// supply the mapping required to convert between ``T`` and a string. template std::enable_if_t::value> - store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value, - ArrayRef> Mapping) { + store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, T Value) { + ArrayRef> Mapping = + OptionEnumMapping::getEnumMapping(); auto Iter = llvm::find_if( - Mapping, [&](const std::pair &NameAndEnum) { - return NameAndEnum.second == Value; + Mapping, [&](const std::pair &NameAndEnum) { + return NameAndEnum.first == Value; }); assert(Iter != Mapping.end() && "Unknown Case Value"); - store(Options, LocalName, Iter->first); + store(Options, LocalName, Iter->second); } private: - using NameAndValue = std::pair; + using NameAndValue = std::pair; llvm::Expected getEnumInt(StringRef LocalName, ArrayRef Mapping, @@ -422,12 +436,14 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback { template std::enable_if_t::value, std::vector> - typeEraseMapping(ArrayRef> Mapping) { + typeEraseMapping() { + ArrayRef> Mapping = + OptionEnumMapping::getEnumMapping(); std::vector Result; Result.reserve(Mapping.size()); for (auto &MappedItem : Mapping) { - Result.emplace_back(MappedItem.first, - static_cast(MappedItem.second)); + Result.emplace_back(static_cast(MappedItem.first), + MappedItem.second); } return Result; } diff --git a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp index df4dbd5ff180d..11bbcbcb527f5 100644 --- a/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp +++ b/clang-tools-extra/clang-tidy/abseil/StringFindStartswithCheck.cpp @@ -27,7 +27,6 @@ StringFindStartswithCheck::StringFindStartswithCheck(StringRef Name, StringLikeClasses(utils::options::parseStringList( Options.get("StringLikeClasses", "::std::basic_string"))), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), AbseilStringsMatchHeader( Options.get("AbseilStringsMatchHeader", "absl/strings/match.h")) {} @@ -122,8 +121,7 @@ void StringFindStartswithCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "StringLikeClasses", utils::options::serializeStringList(StringLikeClasses)); - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "AbseilStringsMatchHeader", AbseilStringsMatchHeader); } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp index 2be3bc4ab3cd1..f1755d3f9b855 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/InitVariablesCheck.cpp @@ -27,13 +27,11 @@ InitVariablesCheck::InitVariablesCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), MathHeader(Options.get("MathHeader", "math.h")) {} void InitVariablesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "MathHeader", MathHeader); } diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp index b48511287f883..dd0bedd742a40 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProBoundsConstantArrayIndexCheck.cpp @@ -22,7 +22,6 @@ ProBoundsConstantArrayIndexCheck::ProBoundsConstantArrayIndexCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void ProBoundsConstantArrayIndexCheck::storeOptions( diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp index 215ba341f21fd..b90af1521baf5 100644 --- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp @@ -28,6 +28,31 @@ using namespace llvm; namespace clang { namespace tidy { + +template <> struct OptionEnumMapping { + static llvm::ArrayRef> + getEnumMapping() { + static constexpr std::pair + Mapping[] = {{modernize::Confidence::CL_Reasonable, "reasonable"}, + {modernize::Confidence::CL_Safe, "safe"}, + {modernize::Confidence::CL_Risky, "risky"}}; + return makeArrayRef(Mapping); + } +}; + +template <> struct OptionEnumMapping { + static llvm::ArrayRef< + std::pair> + getEnumMapping() { + static constexpr std::pair + Mapping[] = {{modernize::VariableNamer::NS_CamelCase, "CamelCase"}, + {modernize::VariableNamer::NS_CamelBack, "camelBack"}, + {modernize::VariableNamer::NS_LowerCase, "lower_case"}, + {modernize::VariableNamer::NS_UpperCase, "UPPER_CASE"}}; + return makeArrayRef(Mapping); + } +}; + namespace modernize { static const char LoopNameArray[] = "forLoopArray"; @@ -44,25 +69,6 @@ static const char EndVarName[] = "endVar"; static const char DerefByValueResultName[] = "derefByValueResult"; static const char DerefByRefResultName[] = "derefByRefResult"; -static ArrayRef> -getConfidenceMapping() { - static constexpr std::pair Mapping[] = { - {"reasonable", Confidence::CL_Reasonable}, - {"safe", Confidence::CL_Safe}, - {"risky", Confidence::CL_Risky}}; - return makeArrayRef(Mapping); -} - -static ArrayRef> -getStyleMapping() { - static constexpr std::pair Mapping[] = - {{"CamelCase", VariableNamer::NS_CamelCase}, - {"camelBack", VariableNamer::NS_CamelBack}, - {"lower_case", VariableNamer::NS_LowerCase}, - {"UPPER_CASE", VariableNamer::NS_UpperCase}}; - return makeArrayRef(Mapping); -} - // shared matchers static const TypeMatcher AnyType() { return anything(); } @@ -474,15 +480,13 @@ LoopConvertCheck::RangeDescriptor::RangeDescriptor() LoopConvertCheck::LoopConvertCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), TUInfo(new TUTrackingInfo), MaxCopySize(Options.get("MaxCopySize", 16ULL)), - MinConfidence(Options.get("MinConfidence", getConfidenceMapping(), - Confidence::CL_Reasonable)), - NamingStyle(Options.get("NamingStyle", getStyleMapping(), - VariableNamer::NS_CamelCase)) {} + MinConfidence(Options.get("MinConfidence", Confidence::CL_Reasonable)), + NamingStyle(Options.get("NamingStyle", VariableNamer::NS_CamelCase)) {} void LoopConvertCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "MaxCopySize", std::to_string(MaxCopySize)); - Options.store(Opts, "MinConfidence", MinConfidence, getConfidenceMapping()); - Options.store(Opts, "NamingStyle", NamingStyle, getStyleMapping()); + Options.store(Opts, "MinConfidence", MinConfidence); + Options.store(Opts, "NamingStyle", NamingStyle); } void LoopConvertCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp index e34fd7038bb86..c677043946f7f 100644 --- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp @@ -45,7 +45,6 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context, StringRef MakeSmartPtrFunctionName) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), MakeSmartPtrFunctionHeader( Options.get("MakeSmartPtrFunctionHeader", StdMemoryHeader)), @@ -54,8 +53,7 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context, IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)) {} void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "MakeSmartPtrFunctionHeader", MakeSmartPtrFunctionHeader); Options.store(Opts, "MakeSmartPtrFunction", MakeSmartPtrFunctionName); Options.store(Opts, "IgnoreMacros", IgnoreMacros); diff --git a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp index ed1a1a26bb62b..b6dedfbc2b6eb 100644 --- a/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/PassByValueCheck.cpp @@ -121,13 +121,11 @@ collectParamDecls(const CXXConstructorDecl *Ctor, PassByValueCheck::PassByValueCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), ValuesOnly(Options.get("ValuesOnly", false)) {} void PassByValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "ValuesOnly", ValuesOnly); } diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp index 295be200bca6f..f98254dbf7c83 100644 --- a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.cpp @@ -75,12 +75,10 @@ ReplaceAutoPtrCheck::ReplaceAutoPtrCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void ReplaceAutoPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } void ReplaceAutoPtrCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp index 9cfbd87239dce..66917df3e91d2 100644 --- a/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceRandomShuffleCheck.cpp @@ -24,7 +24,6 @@ ReplaceRandomShuffleCheck::ReplaceRandomShuffleCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void ReplaceRandomShuffleCheck::registerMatchers(MatchFinder *Finder) { @@ -52,8 +51,7 @@ void ReplaceRandomShuffleCheck::registerPPCallbacks( void ReplaceRandomShuffleCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } void ReplaceRandomShuffleCheck::check(const MatchFinder::MatchResult &Result) { diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp index d09673fa7f23f..4cbb014867c4d 100644 --- a/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/MoveConstructorInitCheck.cpp @@ -24,7 +24,6 @@ MoveConstructorInitCheck::MoveConstructorInitCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) { @@ -97,8 +96,7 @@ void MoveConstructorInitCheck::registerPPCallbacks( } void MoveConstructorInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } } // namespace performance diff --git a/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp b/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp index d08cec1a2c3ca..597445d0fc266 100644 --- a/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/TypePromotionInMathFnCheck.cpp @@ -32,7 +32,6 @@ TypePromotionInMathFnCheck::TypePromotionInMathFnCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)) {} void TypePromotionInMathFnCheck::registerPPCallbacks( @@ -44,8 +43,7 @@ void TypePromotionInMathFnCheck::registerPPCallbacks( void TypePromotionInMathFnCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } void TypePromotionInMathFnCheck::registerMatchers(MatchFinder *Finder) { diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp index 5b5f2ff994783..5de53b1840f12 100644 --- a/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp +++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryValueParamCheck.cpp @@ -69,7 +69,6 @@ UnnecessaryValueParamCheck::UnnecessaryValueParamCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - utils::IncludeSorter::getMapping(), utils::IncludeSorter::IS_LLVM)), AllowedTypes( utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} @@ -181,8 +180,7 @@ void UnnecessaryValueParamCheck::registerPPCallbacks( void UnnecessaryValueParamCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - utils::IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); Options.store(Opts, "AllowedTypes", utils::options::serializeStringList(AllowedTypes)); } diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index 6e7fcaa4345a5..c885aac89072a 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -26,6 +26,26 @@ using namespace clang::ast_matchers; namespace clang { namespace tidy { + +llvm::ArrayRef< + std::pair> +OptionEnumMapping< + readability::IdentifierNamingCheck::CaseType>::getEnumMapping() { + static constexpr std::pair + Mapping[] = { + {readability::IdentifierNamingCheck::CT_AnyCase, "aNy_CasE"}, + {readability::IdentifierNamingCheck::CT_LowerCase, "lower_case"}, + {readability::IdentifierNamingCheck::CT_UpperCase, "UPPER_CASE"}, + {readability::IdentifierNamingCheck::CT_CamelBack, "camelBack"}, + {readability::IdentifierNamingCheck::CT_CamelCase, "CamelCase"}, + {readability::IdentifierNamingCheck::CT_CamelSnakeCase, + "Camel_Snake_Case"}, + {readability::IdentifierNamingCheck::CT_CamelSnakeBack, + "camel_Snake_Back"}}; + return llvm::makeArrayRef(Mapping); +} + namespace readability { // clang-format off @@ -99,16 +119,6 @@ static StringRef const StyleNames[] = { #undef NAMING_KEYS // clang-format on -static constexpr std::pair - Mapping[] = { - {"aNy_CasE", IdentifierNamingCheck::CT_AnyCase}, - {"lower_case", IdentifierNamingCheck::CT_LowerCase}, - {"UPPER_CASE", IdentifierNamingCheck::CT_UpperCase}, - {"camelBack", IdentifierNamingCheck::CT_CamelBack}, - {"CamelCase", IdentifierNamingCheck::CT_CamelCase}, - {"Camel_Snake_Case", IdentifierNamingCheck::CT_CamelSnakeCase}, - {"camel_Snake_Back", IdentifierNamingCheck::CT_CamelSnakeBack}}; - IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, ClangTidyContext *Context) : RenamerClangTidyCheck(Name, Context), @@ -117,7 +127,7 @@ IdentifierNamingCheck::IdentifierNamingCheck(StringRef Name, for (auto const &Name : StyleNames) { auto CaseOptional = [&]() -> llvm::Optional { - auto ValueOr = Options.get((Name + "Case").str(), makeArrayRef(Mapping)); + auto ValueOr = Options.get((Name + "Case").str()); if (ValueOr) return *ValueOr; llvm::logAllUnhandledErrors( @@ -148,7 +158,7 @@ void IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { if (NamingStyles[i]) { if (NamingStyles[i]->Case) { Options.store(Opts, (StyleNames[i] + "Case").str(), - *NamingStyles[i]->Case, llvm::makeArrayRef(Mapping)); + *NamingStyles[i]->Case); } Options.store(Opts, (StyleNames[i] + "Prefix").str(), NamingStyles[i]->Prefix); diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h index 04bf53fe16b56..0f6c77b2c9a86 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h @@ -75,6 +75,12 @@ class IdentifierNamingCheck final : public RenamerClangTidyCheck { }; } // namespace readability +template <> +struct OptionEnumMapping { + static llvm::ArrayRef< + std::pair> + getEnumMapping(); +}; } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp index f946b3a1a6f97..c9d018f076e76 100644 --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.cpp @@ -175,13 +175,14 @@ Optional IncludeSorter::CreateIncludeInsertion(StringRef FileName, IncludeStmt); } -llvm::ArrayRef> -IncludeSorter::getMapping() { - static constexpr std::pair Mapping[] = - {{"llvm", IS_LLVM}, {"google", IS_Google}}; +} // namespace utils + +llvm::ArrayRef> +OptionEnumMapping::getEnumMapping() { + static constexpr std::pair + Mapping[] = {{utils::IncludeSorter::IS_LLVM, "llvm"}, + {utils::IncludeSorter::IS_Google, "google"}}; return makeArrayRef(Mapping); } - -} // namespace utils } // namespace tidy } // namespace clang diff --git a/clang-tools-extra/clang-tidy/utils/IncludeSorter.h b/clang-tools-extra/clang-tidy/utils/IncludeSorter.h index 7dab2cc536a48..1d8997364e5ce 100644 --- a/clang-tools-extra/clang-tidy/utils/IncludeSorter.h +++ b/clang-tools-extra/clang-tidy/utils/IncludeSorter.h @@ -9,7 +9,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H -#include "../ClangTidy.h" +#include "../ClangTidyCheck.h" #include namespace clang { @@ -25,8 +25,6 @@ class IncludeSorter { /// Supported include styles. enum IncludeStyle { IS_LLVM = 0, IS_Google = 1 }; - static ArrayRef> getMapping(); - /// The classifications of inclusions, in the order they should be sorted. enum IncludeKinds { IK_MainTUInclude = 0, ///< e.g. ``#include "foo.h"`` when editing foo.cc @@ -66,6 +64,11 @@ class IncludeSorter { }; } // namespace utils + +template <> struct OptionEnumMapping { + static ArrayRef> + getEnumMapping(); +}; } // namespace tidy } // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_INCLUDESORTER_H diff --git a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp index 665fd5140ceb2..03af5dd1565f8 100644 --- a/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp +++ b/clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.cpp @@ -33,7 +33,6 @@ TransformerClangTidyCheck::TransformerClangTidyCheck( StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), Rule(MakeRule(getLangOpts(), Options)), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - IncludeSorter::getMapping(), IncludeSorter::IS_LLVM)) { if (Rule) assert(llvm::all_of(Rule->Cases, hasExplanation) && @@ -46,7 +45,6 @@ TransformerClangTidyCheck::TransformerClangTidyCheck(RewriteRule R, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), Rule(std::move(R)), IncludeStyle(Options.getLocalOrGlobal("IncludeStyle", - IncludeSorter::getMapping(), IncludeSorter::IS_LLVM)) { assert(llvm::all_of(Rule->Cases, hasExplanation) && "clang-tidy checks must have an explanation by default;" @@ -112,8 +110,7 @@ void TransformerClangTidyCheck::check( void TransformerClangTidyCheck::storeOptions( ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "IncludeStyle", IncludeStyle, - IncludeSorter::getMapping()); + Options.store(Opts, "IncludeStyle", IncludeStyle); } } // namespace utils diff --git a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp index a089281bf16c4..63f9a06e91bec 100644 --- a/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp +++ b/clang-tools-extra/unittests/clang-tidy/ClangTidyOptionsTest.cpp @@ -6,6 +6,20 @@ namespace clang { namespace tidy { + +enum class Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet }; + +template <> struct OptionEnumMapping { + static llvm::ArrayRef> getEnumMapping() { + static constexpr std::pair Mapping[] = { + {Colours::Red, "Red"}, {Colours::Orange, "Orange"}, + {Colours::Yellow, "Yellow"}, {Colours::Green, "Green"}, + {Colours::Blue, "Blue"}, {Colours::Indigo, "Indigo"}, + {Colours::Violet, "Violet"}}; + return makeArrayRef(Mapping); + } +}; + namespace test { TEST(ParseLineFilter, EmptyFilter) { @@ -208,16 +222,10 @@ TEST(CheckOptionsValidation, ValidIntOptions) { #undef CHECK_ERROR_INT } +// FIXME: Figure out why this test causes crashes on mac os. +#ifndef __APPLE__ TEST(ValidConfiguration, ValidEnumOptions) { - enum class Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet }; - static constexpr std::pair Mapping[] = { - {"Red", Colours::Red}, {"Orange", Colours::Orange}, - {"Yellow", Colours::Yellow}, {"Green", Colours::Green}, - {"Blue", Colours::Blue}, {"Indigo", Colours::Indigo}, - {"Violet", Colours::Violet}}; - static const auto Map = makeArrayRef(Mapping); - ClangTidyOptions Options; auto &CheckOptions = Options.CheckOptions; @@ -237,34 +245,37 @@ TEST(ValidConfiguration, ValidEnumOptions) { #define CHECK_ERROR_ENUM(Name, Expected) \ CHECK_ERROR(Name, UnparseableEnumOptionError, Expected) - CHECK_VAL(TestCheck.getLocal("Valid", Map), Colours::Red); - CHECK_VAL(TestCheck.getGlobal("GlobalValid", Map), Colours::Violet); - CHECK_VAL(TestCheck.getLocal("ValidWrongCase", Map, /*IgnoreCase*/ true), - Colours::Red); + CHECK_VAL(TestCheck.getIntLocal("Valid"), Colours::Red); + CHECK_VAL(TestCheck.getIntGlobal("GlobalValid"), Colours::Violet); + CHECK_VAL( - TestCheck.getGlobal("GlobalValidWrongCase", Map, /*IgnoreCase*/ true), - Colours::Violet); - CHECK_ERROR_ENUM(TestCheck.getLocal("Invalid", Map), + TestCheck.getIntLocal("ValidWrongCase", /*IgnoreCase*/ true), + Colours::Red); + CHECK_VAL(TestCheck.getIntGlobal("GlobalValidWrongCase", + /*IgnoreCase*/ true), + Colours::Violet); + CHECK_ERROR_ENUM(TestCheck.getIntLocal("Invalid"), "invalid configuration value " "'Scarlet' for option 'test.Invalid'"); - CHECK_ERROR_ENUM(TestCheck.getLocal("ValidWrongCase", Map), + CHECK_ERROR_ENUM(TestCheck.getIntLocal("ValidWrongCase"), "invalid configuration value 'rED' for option " "'test.ValidWrongCase'; did you mean 'Red'?"); - CHECK_ERROR_ENUM(TestCheck.getLocal("NearMiss", Map), + CHECK_ERROR_ENUM(TestCheck.getIntLocal("NearMiss"), "invalid configuration value 'Oragne' for option " "'test.NearMiss'; did you mean 'Orange'?"); - CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalInvalid", Map), + CHECK_ERROR_ENUM(TestCheck.getIntGlobal("GlobalInvalid"), "invalid configuration value " "'Purple' for option 'GlobalInvalid'"); - CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalValidWrongCase", Map), + CHECK_ERROR_ENUM(TestCheck.getIntGlobal("GlobalValidWrongCase"), "invalid configuration value 'vIOLET' for option " "'GlobalValidWrongCase'; did you mean 'Violet'?"); - CHECK_ERROR_ENUM(TestCheck.getGlobal("GlobalNearMiss", Map), + CHECK_ERROR_ENUM(TestCheck.getIntGlobal("GlobalNearMiss"), "invalid configuration value 'Yelow' for option " "'GlobalNearMiss'; did you mean 'Yellow'?"); #undef CHECK_ERROR_ENUM } +#endif #undef CHECK_VAL #undef CHECK_ERROR From 4abdcdb45ee22d77dd64a71cb41e967d35361280 Mon Sep 17 00:00:00 2001 From: Nathan James Date: Sat, 11 Jul 2020 10:42:57 +0100 Subject: [PATCH 013/771] Fix gn builds after 943660fd1 --- llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn index 3bf40626fc808..bfc2c7ae51106 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn @@ -7,7 +7,7 @@ static_library("OpenMP") { ] public_deps = [ "//llvm/include/llvm/Frontend/OpenMP:public_tablegen" ] sources = [ - "OMPConstants.cpp", + "OMP.cpp", "OMPContext.cpp", "OMPIRBuilder.cpp", ] From 8fb91dfeed1bd1ffdfd31a345e1bf7cf0b7c86e2 Mon Sep 17 00:00:00 2001 From: Nathan James Date: Sat, 11 Jul 2020 10:45:17 +0100 Subject: [PATCH 014/771] Revert "Fix gn builds after 943660fd1" This reverts commit 4abdcdb45ee22d77dd64a71cb41e967d35361280. --- llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn index bfc2c7ae51106..3bf40626fc808 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn @@ -7,7 +7,7 @@ static_library("OpenMP") { ] public_deps = [ "//llvm/include/llvm/Frontend/OpenMP:public_tablegen" ] sources = [ - "OMP.cpp", + "OMPConstants.cpp", "OMPContext.cpp", "OMPIRBuilder.cpp", ] From 35af6f11e04b777b73035f59bfabb68a08ca4ad9 Mon Sep 17 00:00:00 2001 From: Nathan James Date: Sat, 11 Jul 2020 11:42:05 +0100 Subject: [PATCH 015/771] Reland Fix gn build after 943660f --- llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn index 3bf40626fc808..07b265bcb288b 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn @@ -7,7 +7,7 @@ static_library("OpenMP") { ] public_deps = [ "//llvm/include/llvm/Frontend/OpenMP:public_tablegen" ] sources = [ - "OMPConstants.cpp", + "OMP.cpp.inc", "OMPContext.cpp", "OMPIRBuilder.cpp", ] From 09a95f51fb1fb86442418d891f67a43e2a3ca698 Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Sat, 11 Jul 2020 06:43:28 -0400 Subject: [PATCH 016/771] [gn build] (manually) merge 943660fd15f193 --- llvm/lib/Frontend/OpenMP/CMakeLists.txt | 2 +- .../llvm/include/llvm/Frontend/OpenMP/BUILD.gn | 8 -------- .../gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn | 13 +++++++++++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Frontend/OpenMP/CMakeLists.txt b/llvm/lib/Frontend/OpenMP/CMakeLists.txt index f88e3ed986623..068283fd82e07 100644 --- a/llvm/lib/Frontend/OpenMP/CMakeLists.txt +++ b/llvm/lib/Frontend/OpenMP/CMakeLists.txt @@ -15,4 +15,4 @@ add_llvm_component_library(LLVMFrontendOpenMP intrinsics_gen omp_gen omp_cpp - ) \ No newline at end of file + ) diff --git a/llvm/utils/gn/secondary/llvm/include/llvm/Frontend/OpenMP/BUILD.gn b/llvm/utils/gn/secondary/llvm/include/llvm/Frontend/OpenMP/BUILD.gn index 9942a3647b58e..a18f8db5f5ebd 100644 --- a/llvm/utils/gn/secondary/llvm/include/llvm/Frontend/OpenMP/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/include/llvm/Frontend/OpenMP/BUILD.gn @@ -6,13 +6,6 @@ tablegen("OMP") { output_name = "OMP.h.inc" } -tablegen("OMPImpl") { - visibility = [ ":public_tablegen" ] - args = [ "-gen-directive-impl" ] - td_file = "OMP.td" - output_name = "OMP.cpp.inc" -} - # Groups all tablegen() calls that create .inc files that are included in # Frontent/OpenMP's public headers (just one so far). # //llvm/lib/Frontend/OpenMP has this as a public_dep, so targets depending on @@ -21,6 +14,5 @@ group("public_tablegen") { public_deps = [ # Frontend/OpenMP's public headers include OMP.h.inc. ":OMP", - ":OMPImpl", ] } diff --git a/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn index 07b265bcb288b..688a25e3c1df1 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Frontend/OpenMP/BUILD.gn @@ -1,14 +1,23 @@ +import("//llvm/utils/TableGen/tablegen.gni") + +tablegen("OMPImpl") { + visibility = [ ":OpenMP" ] + args = [ "-gen-directive-impl" ] + td_file = "//llvm/include/llvm/Frontend/OpenMP/OMP.td" + output_name = "OMP.cpp" +} + static_library("OpenMP") { output_name = "LLVMFrontendOpenMP" deps = [ + ":OMPImpl", "//llvm/lib/IR", "//llvm/lib/Support", "//llvm/lib/Transforms/Utils", ] public_deps = [ "//llvm/include/llvm/Frontend/OpenMP:public_tablegen" ] sources = [ - "OMP.cpp.inc", "OMPContext.cpp", "OMPIRBuilder.cpp", - ] + ] + get_target_outputs(":OMPImpl") } From 4500db8c59621a31c622862a2946457fdee481ce Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 11 Jul 2020 13:52:33 +0300 Subject: [PATCH 017/771] Revert "Reland "[InstCombine] Lower infinite combine loop detection thresholds""" And there's a new hit: https://bugs.llvm.org/show_bug.cgi?id=46680 This reverts commit 7103c87596efccd532e9fe04a6ba6a200fed8481. --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index e810b3de25bc8..d1c1e54188251 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -123,13 +123,8 @@ STATISTIC(NumReassoc , "Number of reassociations"); DEBUG_COUNTER(VisitCounter, "instcombine-visit", "Controls which instructions are visited"); -// FIXME: these limits eventually should be as low as 2. static constexpr unsigned InstCombineDefaultMaxIterations = 1000; -#ifndef NDEBUG -static constexpr unsigned InstCombineDefaultInfiniteLoopThreshold = 100; -#else static constexpr unsigned InstCombineDefaultInfiniteLoopThreshold = 1000; -#endif static cl::opt EnableCodeSinking("instcombine-code-sinking", cl::desc("Enable code sinking"), From f7907e9d223d8484f9afd457ba614c2db2ae4743 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Fri, 19 Jun 2020 23:55:05 +0300 Subject: [PATCH 018/771] [TRE] allow TRE for non-capturing calls. The current implementation of Tail Recursion Elimination has a very restricted pre-requisite: AllCallsAreTailCalls. i.e. it requires that no function call receives a pointer to local stack. Generally, function calls that receive a pointer to local stack but do not capture it - should not break TRE. This fix allows us to do TRE if it is proved that no pointer to the local stack is escaped. Reviewed by: efriedma Differential Revision: https://reviews.llvm.org/D82085 --- .../Scalar/TailRecursionElimination.cpp | 113 ++++++---------- llvm/test/Transforms/TailCallElim/basic.ll | 7 +- .../TailCallElim/tre-multiple-exits.ll | 125 ++++++++++++++++++ .../tre-noncapturing-alloca-calls.ll | 74 +++++++++++ 4 files changed, 247 insertions(+), 72 deletions(-) create mode 100644 llvm/test/Transforms/TailCallElim/tre-multiple-exits.ll create mode 100644 llvm/test/Transforms/TailCallElim/tre-noncapturing-alloca-calls.ll diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp index 5bb1d54d7d127..bfd312a52ea58 100644 --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -81,6 +81,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Local.h" using namespace llvm; #define DEBUG_TYPE "tailcallelim" @@ -92,7 +93,10 @@ STATISTIC(NumAccumAdded, "Number of accumulators introduced"); /// Scan the specified function for alloca instructions. /// If it contains any dynamic allocas, returns false. static bool canTRE(Function &F) { - // Because of PR962, we don't TRE dynamic allocas. + // TODO: We don't do TRE if dynamic allocas are used. + // Dynamic allocas allocate stack space which should be + // deallocated before new iteration started. That is + // currently not implemented. return llvm::all_of(instructions(F), [](Instruction &I) { auto *AI = dyn_cast(&I); return !AI || AI->isStaticAlloca(); @@ -185,11 +189,9 @@ struct AllocaDerivedValueTracker { }; } -static bool markTails(Function &F, bool &AllCallsAreTailCalls, - OptimizationRemarkEmitter *ORE) { +static bool markTails(Function &F, OptimizationRemarkEmitter *ORE) { if (F.callsFunctionThatReturnsTwice()) return false; - AllCallsAreTailCalls = true; // The local stack holds all alloca instructions and all byval arguments. AllocaDerivedValueTracker Tracker; @@ -272,11 +274,8 @@ static bool markTails(Function &F, bool &AllCallsAreTailCalls, } } - if (!IsNoTail && Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) { + if (!IsNoTail && Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) DeferredTails.push_back(CI); - } else { - AllCallsAreTailCalls = false; - } } for (auto *SuccBB : make_range(succ_begin(BB), succ_end(BB))) { @@ -313,8 +312,6 @@ static bool markTails(Function &F, bool &AllCallsAreTailCalls, LLVM_DEBUG(dbgs() << "Marked as tail call candidate: " << *CI << "\n"); CI->setTailCall(); Modified = true; - } else { - AllCallsAreTailCalls = false; } } @@ -325,7 +322,16 @@ static bool markTails(Function &F, bool &AllCallsAreTailCalls, /// instruction from after the call to before the call, assuming that all /// instructions between the call and this instruction are movable. /// -static bool canMoveAboveCall(Instruction *I, CallInst *CI, AliasAnalysis *AA) { +static bool canMoveAboveCall(Instruction *I, CallInst *CI, AliasAnalysis *AA, + DenseMap &AllocaForValue) { + if (isa(I)) + return true; + + if (const IntrinsicInst *II = dyn_cast(I)) + if (II->getIntrinsicID() == Intrinsic::lifetime_end && + llvm::findAllocaForValue(II->getArgOperand(1), AllocaForValue)) + return true; + // FIXME: We can move load/store/call/free instructions above the call if the // call does not mod/ref the memory location being processed. if (I->mayHaveSideEffects()) // This also handles volatile loads. @@ -392,7 +398,6 @@ class TailRecursionEliminator { // createTailRecurseLoopHeader the first time we find a call we can eliminate. BasicBlock *HeaderBB = nullptr; SmallVector ArgumentPHIs; - bool RemovableCallsMustBeMarkedTail = false; // PHI node to store our return value. PHINode *RetPN = nullptr; @@ -414,13 +419,15 @@ class TailRecursionEliminator { // The instruction doing the accumulating. Instruction *AccumulatorRecursionInstr = nullptr; + // The cache for pairs. + DenseMap AllocaForValue; + TailRecursionEliminator(Function &F, const TargetTransformInfo *TTI, AliasAnalysis *AA, OptimizationRemarkEmitter *ORE, DomTreeUpdater &DTU) : F(F), TTI(TTI), AA(AA), ORE(ORE), DTU(DTU) {} - CallInst *findTRECandidate(Instruction *TI, - bool CannotTailCallElimCallsMarkedTail); + CallInst *findTRECandidate(Instruction *TI); void createTailRecurseLoopHeader(CallInst *CI); @@ -428,11 +435,9 @@ class TailRecursionEliminator { bool eliminateCall(CallInst *CI); - bool foldReturnAndProcessPred(ReturnInst *Ret, - bool CannotTailCallElimCallsMarkedTail); + bool foldReturnAndProcessPred(ReturnInst *Ret); - bool processReturningBlock(ReturnInst *Ret, - bool CannotTailCallElimCallsMarkedTail); + bool processReturningBlock(ReturnInst *Ret); void cleanupAndFinalize(); @@ -443,8 +448,7 @@ class TailRecursionEliminator { }; } // namespace -CallInst *TailRecursionEliminator::findTRECandidate( - Instruction *TI, bool CannotTailCallElimCallsMarkedTail) { +CallInst *TailRecursionEliminator::findTRECandidate(Instruction *TI) { BasicBlock *BB = TI->getParent(); if (&BB->front() == TI) // Make sure there is something before the terminator. @@ -464,9 +468,9 @@ CallInst *TailRecursionEliminator::findTRECandidate( --BBI; } - // If this call is marked as a tail call, and if there are dynamic allocas in - // the function, we cannot perform this optimization. - if (CI->isTailCall() && CannotTailCallElimCallsMarkedTail) + assert((!CI->isTailCall() || !CI->isNoTailCall()) && + "Incompatible call site attributes(Tail,NoTail)"); + if (!CI->isTailCall()) return nullptr; // As a special case, detect code like this: @@ -498,26 +502,13 @@ void TailRecursionEliminator::createTailRecurseLoopHeader(CallInst *CI) { BranchInst *BI = BranchInst::Create(HeaderBB, NewEntry); BI->setDebugLoc(CI->getDebugLoc()); - // If this function has self recursive calls in the tail position where some - // are marked tail and some are not, only transform one flavor or another. - // We have to choose whether we move allocas in the entry block to the new - // entry block or not, so we can't make a good choice for both. We make this - // decision here based on whether the first call we found to remove is - // marked tail. - // NOTE: We could do slightly better here in the case that the function has - // no entry block allocas. - RemovableCallsMustBeMarkedTail = CI->isTailCall(); - - // If this tail call is marked 'tail' and if there are any allocas in the - // entry block, move them up to the new entry block. - if (RemovableCallsMustBeMarkedTail) - // Move all fixed sized allocas from HeaderBB to NewEntry. - for (BasicBlock::iterator OEBI = HeaderBB->begin(), E = HeaderBB->end(), - NEBI = NewEntry->begin(); - OEBI != E;) - if (AllocaInst *AI = dyn_cast(OEBI++)) - if (isa(AI->getArraySize())) - AI->moveBefore(&*NEBI); + // Move all fixed sized allocas from HeaderBB to NewEntry. + for (BasicBlock::iterator OEBI = HeaderBB->begin(), E = HeaderBB->end(), + NEBI = NewEntry->begin(); + OEBI != E;) + if (AllocaInst *AI = dyn_cast(OEBI++)) + if (isa(AI->getArraySize())) + AI->moveBefore(&*NEBI); // Now that we have created a new block, which jumps to the entry // block, insert a PHI node for each argument of the function. @@ -592,7 +583,7 @@ bool TailRecursionEliminator::eliminateCall(CallInst *CI) { Instruction *AccRecInstr = nullptr; BasicBlock::iterator BBI(CI); for (++BBI; &*BBI != Ret; ++BBI) { - if (canMoveAboveCall(&*BBI, CI, AA)) + if (canMoveAboveCall(&*BBI, CI, AA, AllocaForValue)) continue; // If we can't move the instruction above the call, it might be because it @@ -620,9 +611,6 @@ bool TailRecursionEliminator::eliminateCall(CallInst *CI) { if (!HeaderBB) createTailRecurseLoopHeader(CI); - if (RemovableCallsMustBeMarkedTail && !CI->isTailCall()) - return false; - // Ok, now that we know we have a pseudo-entry block WITH all of the // required PHI nodes, add entries into the PHI node for the actual // parameters passed into the tail-recursive call. @@ -672,8 +660,7 @@ bool TailRecursionEliminator::eliminateCall(CallInst *CI) { return true; } -bool TailRecursionEliminator::foldReturnAndProcessPred( - ReturnInst *Ret, bool CannotTailCallElimCallsMarkedTail) { +bool TailRecursionEliminator::foldReturnAndProcessPred(ReturnInst *Ret) { BasicBlock *BB = Ret->getParent(); bool Change = false; @@ -698,8 +685,7 @@ bool TailRecursionEliminator::foldReturnAndProcessPred( while (!UncondBranchPreds.empty()) { BranchInst *BI = UncondBranchPreds.pop_back_val(); BasicBlock *Pred = BI->getParent(); - if (CallInst *CI = - findTRECandidate(BI, CannotTailCallElimCallsMarkedTail)) { + if (CallInst *CI = findTRECandidate(BI)) { LLVM_DEBUG(dbgs() << "FOLDING: " << *BB << "INTO UNCOND BRANCH PRED: " << *Pred); FoldReturnIntoUncondBranch(Ret, BB, Pred, &DTU); @@ -720,9 +706,8 @@ bool TailRecursionEliminator::foldReturnAndProcessPred( return Change; } -bool TailRecursionEliminator::processReturningBlock( - ReturnInst *Ret, bool CannotTailCallElimCallsMarkedTail) { - CallInst *CI = findTRECandidate(Ret, CannotTailCallElimCallsMarkedTail); +bool TailRecursionEliminator::processReturningBlock(ReturnInst *Ret) { + CallInst *CI = findTRECandidate(Ret); if (!CI) return false; @@ -810,35 +795,25 @@ bool TailRecursionEliminator::eliminate(Function &F, return false; bool MadeChange = false; - bool AllCallsAreTailCalls = false; - MadeChange |= markTails(F, AllCallsAreTailCalls, ORE); - if (!AllCallsAreTailCalls) - return MadeChange; + MadeChange |= markTails(F, ORE); // If this function is a varargs function, we won't be able to PHI the args // right, so don't even try to convert it... if (F.getFunctionType()->isVarArg()) return MadeChange; - // If false, we cannot perform TRE on tail calls marked with the 'tail' - // attribute, because doing so would cause the stack size to increase (real - // TRE would deallocate variable sized allocas, TRE doesn't). - bool CanTRETailMarkedCall = canTRE(F); + if (!canTRE(F)) + return MadeChange; TailRecursionEliminator TRE(F, TTI, AA, ORE, DTU); // Change any tail recursive calls to loops. - // - // FIXME: The code generator produces really bad code when an 'escaping - // alloca' is changed from being a static alloca to being a dynamic alloca. - // Until this is resolved, disable this transformation if that would ever - // happen. This bug is PR962. for (Function::iterator BBI = F.begin(), E = F.end(); BBI != E; /*in loop*/) { BasicBlock *BB = &*BBI++; // foldReturnAndProcessPred may delete BB. if (ReturnInst *Ret = dyn_cast(BB->getTerminator())) { - bool Change = TRE.processReturningBlock(Ret, !CanTRETailMarkedCall); + bool Change = TRE.processReturningBlock(Ret); if (!Change && BB->getFirstNonPHIOrDbg() == Ret) - Change = TRE.foldReturnAndProcessPred(Ret, !CanTRETailMarkedCall); + Change = TRE.foldReturnAndProcessPred(Ret); MadeChange |= Change; } } diff --git a/llvm/test/Transforms/TailCallElim/basic.ll b/llvm/test/Transforms/TailCallElim/basic.ll index 6116014a024b1..669210da6314b 100644 --- a/llvm/test/Transforms/TailCallElim/basic.ll +++ b/llvm/test/Transforms/TailCallElim/basic.ll @@ -12,15 +12,16 @@ define void @test0() { ret void } -; PR615. Make sure that we do not move the alloca so that it interferes with the tail call. +; Make sure that we do not do TRE if pointer to local stack +; escapes through function call. define i32 @test1() { ; CHECK: i32 @test1() ; CHECK-NEXT: alloca %A = alloca i32 ; [#uses=2] store i32 5, i32* %A call void @use(i32* %A) -; CHECK: tail call i32 @test1 - %X = tail call i32 @test1() ; [#uses=1] +; CHECK: call i32 @test1 + %X = call i32 @test1() ; [#uses=1] ret i32 %X } diff --git a/llvm/test/Transforms/TailCallElim/tre-multiple-exits.ll b/llvm/test/Transforms/TailCallElim/tre-multiple-exits.ll new file mode 100644 index 0000000000000..8f69087dd879d --- /dev/null +++ b/llvm/test/Transforms/TailCallElim/tre-multiple-exits.ll @@ -0,0 +1,125 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s + +; This test checks that TRE would be done for only one recursive call. +; The test_multiple_exits function has three recursive calls. +; First recursive call could not be eliminated because there is +; escaped pointer to local variable. Second recursive call could +; be eliminated. Thrid recursive call could not be eliminated since +; this is not last call. Thus, test checks that TRE would be done +; for only second recursive call. + +; IR for that test was generated from the following C++ source: +; +; void capture_arg (int*); +; void test_multiple_exits (int param); +; if (param >= 0 && param < 10) { +; int temp; +; capture_arg(&temp); +; // TRE could not be done because pointer to local +; // variable "temp" is escaped. +; test_multiple_exits(param + 1); +; } else if (param >=10 && param < 20) { +; // TRE should be done. +; test_multiple_exits(param + 1); +; } else if (param >= 20 && param < 22) { +; // TRE could not be done since recursive +; // call is not last call. +; test_multiple_exits(param + 1); +; func(); +; } +; +; return; +; } + +; Function Attrs: noinline optnone uwtable +declare void @_Z11capture_argPi(i32* %param) #0 + +; Function Attrs: noinline optnone uwtable +declare void @_Z4funcv() #0 + +; Function Attrs: noinline nounwind uwtable +define dso_local void @_Z19test_multiple_exitsi(i32 %param) local_unnamed_addr #2 { +; CHECK-LABEL: @_Z19test_multiple_exitsi( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TEMP:%.*]] = alloca i32, align 4 +; CHECK-NEXT: br label [[TAILRECURSE:%.*]] +; CHECK: tailrecurse: +; CHECK-NEXT: [[PARAM_TR:%.*]] = phi i32 [ [[PARAM:%.*]], [[ENTRY:%.*]] ], [ [[ADD6:%.*]], [[IF_THEN5:%.*]] ] +; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[PARAM_TR]], 10 +; CHECK-NEXT: br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TEMP]] to i8* +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[TMP1]]) #1 +; CHECK-NEXT: call void @_Z11capture_argPi(i32* nonnull [[TEMP]]) +; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[PARAM_TR]], 1 +; CHECK-NEXT: call void @_Z19test_multiple_exitsi(i32 [[ADD]]) +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TMP1]]) #1 +; CHECK-NEXT: br label [[IF_END14:%.*]] +; CHECK: if.else: +; CHECK-NEXT: [[PARAM_OFF:%.*]] = add i32 [[PARAM_TR]], -10 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[PARAM_OFF]], 10 +; CHECK-NEXT: br i1 [[TMP2]], label [[IF_THEN5]], label [[IF_ELSE7:%.*]] +; CHECK: if.then5: +; CHECK-NEXT: [[ADD6]] = add nuw nsw i32 [[PARAM_TR]], 1 +; CHECK-NEXT: br label [[TAILRECURSE]] +; CHECK: if.else7: +; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[PARAM_TR]], -2 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 20 +; CHECK-NEXT: br i1 [[TMP4]], label [[IF_THEN11:%.*]], label [[IF_END14]] +; CHECK: if.then11: +; CHECK-NEXT: [[ADD12:%.*]] = add nsw i32 [[PARAM_TR]], 1 +; CHECK-NEXT: tail call void @_Z19test_multiple_exitsi(i32 [[ADD12]]) +; CHECK-NEXT: tail call void @_Z4funcv() +; CHECK-NEXT: ret void +; CHECK: if.end14: +; CHECK-NEXT: ret void +; +entry: + %temp = alloca i32, align 4 + %0 = icmp ult i32 %param, 10 + br i1 %0, label %if.then, label %if.else + +if.then: ; preds = %entry + %1 = bitcast i32* %temp to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %1) #2 + call void @_Z11capture_argPi(i32* nonnull %temp) + %add = add nuw nsw i32 %param, 1 + call void @_Z19test_multiple_exitsi(i32 %add) + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %1) #2 + br label %if.end14 + +if.else: ; preds = %entry + %param.off = add i32 %param, -10 + %2 = icmp ult i32 %param.off, 10 + br i1 %2, label %if.then5, label %if.else7 + +if.then5: ; preds = %if.else + %add6 = add nuw nsw i32 %param, 1 + call void @_Z19test_multiple_exitsi(i32 %add6) + br label %if.end14 + +if.else7: ; preds = %if.else + %3 = and i32 %param, -2 + %4 = icmp eq i32 %3, 20 + br i1 %4, label %if.then11, label %if.end14 + +if.then11: ; preds = %if.else7 + %add12 = add nsw i32 %param, 1 + call void @_Z19test_multiple_exitsi(i32 %add12) + call void @_Z4funcv() + br label %if.end14 + +if.end14: ; preds = %if.then5, %if.then11, %if.else7, %if.then + ret void +} + +; Function Attrs: argmemonly nounwind willreturn +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2 + +; Function Attrs: argmemonly nounwind willreturn +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2 + +attributes #0 = { nofree noinline norecurse nounwind uwtable } +attributes #1 = { nounwind uwtable } +attributes #2 = { argmemonly nounwind willreturn } diff --git a/llvm/test/Transforms/TailCallElim/tre-noncapturing-alloca-calls.ll b/llvm/test/Transforms/TailCallElim/tre-noncapturing-alloca-calls.ll new file mode 100644 index 0000000000000..2168437fc5706 --- /dev/null +++ b/llvm/test/Transforms/TailCallElim/tre-noncapturing-alloca-calls.ll @@ -0,0 +1,74 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s + +; IR for that test was generated from the following C++ source: +; +;int count; +;__attribute__((noinline)) void globalIncrement(const int* param) { count += *param; } +; +;void test(int recurseCount) +;{ +; if (recurseCount == 0) return; +; int temp = 10; +; globalIncrement(&temp); +; test(recurseCount - 1); +;} +; + +@count = dso_local local_unnamed_addr global i32 0, align 4 + +; Function Attrs: nofree noinline norecurse nounwind uwtable +declare void @_Z15globalIncrementPKi(i32* nocapture readonly %param) #0 + +; Test that TRE could be done for recursive tail routine containing +; call to function receiving a pointer to local stack. + +; Function Attrs: nounwind uwtable +define dso_local void @_Z4testi(i32 %recurseCount) local_unnamed_addr #1 { +; CHECK-LABEL: @_Z4testi( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TEMP:%.*]] = alloca i32, align 4 +; CHECK-NEXT: br label [[TAILRECURSE:%.*]] +; CHECK: tailrecurse: +; CHECK-NEXT: [[RECURSECOUNT_TR:%.*]] = phi i32 [ [[RECURSECOUNT:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[IF_END:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RECURSECOUNT_TR]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[TEMP]] to i8* +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[TMP0]]) +; CHECK-NEXT: store i32 10, i32* [[TEMP]], align 4 +; CHECK-NEXT: call void @_Z15globalIncrementPKi(i32* nonnull [[TEMP]]) +; CHECK-NEXT: [[SUB]] = add nsw i32 [[RECURSECOUNT_TR]], -1 +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TMP0]]) +; CHECK-NEXT: br label [[TAILRECURSE]] +; CHECK: return: +; CHECK-NEXT: ret void +; +entry: + %temp = alloca i32, align 4 + %cmp = icmp eq i32 %recurseCount, 0 + br i1 %cmp, label %return, label %if.end + +if.end: ; preds = %entry + %0 = bitcast i32* %temp to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #6 + store i32 10, i32* %temp, align 4 + call void @_Z15globalIncrementPKi(i32* nonnull %temp) + %sub = add nsw i32 %recurseCount, -1 + call void @_Z4testi(i32 %sub) + call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #6 + br label %return + +return: ; preds = %entry, %if.end + ret void +} + +; Function Attrs: argmemonly nounwind willreturn +declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2 + +; Function Attrs: argmemonly nounwind willreturn +declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2 + +attributes #0 = { nofree noinline norecurse nounwind uwtable } +attributes #1 = { nounwind uwtable } +attributes #2 = { argmemonly nounwind willreturn } From d7a05698efcfa6c596bcaadd8d5154612990f8f3 Mon Sep 17 00:00:00 2001 From: Christudasan Devadasan Date: Sat, 11 Jul 2020 00:19:51 +0530 Subject: [PATCH 019/771] [AMDGPU] Move LowerSwitch pass to CodeGenPrepare. It is possible that LowerSwitch pass leaves certain blocks unreachable from the entry. If not removed, these dead blocks can cause undefined behavior in the subsequent passes. It caused a crash in the AMDGPU backend after the instruction selection when a PHI node has its incoming values coming from these unreachable blocks. In the AMDGPU pass flow, the last invocation of UnreachableBlockElim precedes where LowerSwitch is currently placed and eventually missed out on the opportunity to get these blocks eliminated. This patch ensures that LowerSwitch pass get inserted earlier to make use of the existing unreachable block elimination pass. Reviewed By: sameerds, arsenm Differential Revision: https://reviews.llvm.org/D83584 --- .../lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 7 ++- .../switch-default-block-unreachable.ll | 60 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AMDGPU/switch-default-block-unreachable.ll diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index 8604f5005eb2b..b4b10835837cd 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp @@ -787,10 +787,15 @@ void AMDGPUPassConfig::addCodeGenPrepare() { if (EnableLoadStoreVectorizer) addPass(createLoadStoreVectorizerPass()); + + // LowerSwitch pass may introduce unreachable blocks that can + // cause unexpected behavior for subsequent passes. Placing it + // here seems better that these blocks would get cleaned up by + // UnreachableBlockElim inserted next in the pass flow. + addPass(createLowerSwitchPass()); } bool AMDGPUPassConfig::addPreISel() { - addPass(createLowerSwitchPass()); addPass(createFlattenCFGPass()); return false; } diff --git a/llvm/test/CodeGen/AMDGPU/switch-default-block-unreachable.ll b/llvm/test/CodeGen/AMDGPU/switch-default-block-unreachable.ll new file mode 100644 index 0000000000000..13c4dc80be156 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/switch-default-block-unreachable.ll @@ -0,0 +1,60 @@ +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx908 -verify-machineinstrs -stop-after=amdgpu-isel -o - %s | FileCheck -check-prefix=GCN %s +define void @test() #1 { + ; Clean up the unreachable blocks introduced with LowerSwitch pass. + ; This test ensures that, in the pass flow, UnreachableBlockElim pass + ; follows the LowerSwitch. Otherwise, this testcase will crash + ; immediately after the instruction selection due to the incomplete + ; PHI node in an MBB whose incoming values were never codegenerated. + ; + ; GCN-LABEL: name: test + ; GCN: bb.{{[0-9]+}}.entry: + ; GCN: bb.{{[0-9]+}}.entry.true.blk: + ; GCN: bb.{{[0-9]+}}.entry.false.blk: + ; GCN: bb.{{[0-9]+}}.switch.blk: + + ; GCN-NOT: bb.{{[0-9]+}}.preheader.blk + ; GCN-NOT: bb.{{[0-9]+}}.pre.false.blk: + ; GCN-NOT: bb.{{[0-9]+}}.unreach.blk: + ; GCN-NOT: PHI + + ; GCN: bb.{{[0-9]+}}.exit: + entry: + %idx = tail call i32 @llvm.amdgcn.workitem.id.x() #0 + br i1 undef, label %entry.true.blk, label %entry.false.blk + + entry.true.blk: ; preds = %entry + %exit.cmp = icmp ult i32 %idx, 3 + br i1 %exit.cmp, label %switch.blk, label %exit + + entry.false.blk: ; preds = %entry + unreachable + + switch.blk: ; preds = %entry.true.blk + switch i32 %idx, label %preheader.blk [ + i32 0, label %exit + i32 1, label %exit + i32 2, label %exit + ] + + preheader.blk: ; preds = %switch.blk + %pre.exit = icmp ult i32 %idx, 5 + br i1 %pre.exit, label %unreach.blk, label %pre.false.blk + + pre.false.blk: ; preds = %preheader.blk + %call.pre.false = tail call i32 @func(i32 %idx) #0 + br label %unreach.blk + + unreach.blk: ; preds = %preheader.blk, %pre.false.blk + %phi.val = phi i32 [ %call.pre.false, %pre.false.blk ], [ undef, %preheader.blk ] + store i32 %phi.val, i32* undef + unreachable + + exit: ; preds = %switch.blk + ret void +} + +declare i32 @llvm.amdgcn.workitem.id.x() #0 +declare i32 @func(i32)#0 + +attributes #0 = { nounwind readnone } +attributes #1 = { nounwind } From 850b150cff3dfb5f2113d9c3c483e2d22b318ced Mon Sep 17 00:00:00 2001 From: sstefan1 Date: Sat, 11 Jul 2020 14:24:56 +0200 Subject: [PATCH 020/771] [Attributor][NFC] Add more debug output for deleted functions --- llvm/lib/Transforms/IPO/Attributor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 6d7f08bfbe07c..7f252079e0532 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -1180,6 +1180,9 @@ ChangeStatus Attributor::cleanupIR() { } } + LLVM_DEBUG(dbgs() << "[Attributor] DeadInsts size: " << DeadInsts.size() + << "\n"); + RecursivelyDeleteTriviallyDeadInstructions(DeadInsts); if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) { @@ -1238,6 +1241,9 @@ ChangeStatus Attributor::cleanupIR() { NumFnDeleted += ToBeDeletedFunctions.size(); + LLVM_DEBUG(dbgs() << "[Attributor] Deleted " << NumFnDeleted + << " functions after manifest.\n"); + #ifdef EXPENSIVE_CHECKS for (Function *F : Functions) { if (ToBeDeletedFunctions.count(F)) From 0b4cf802fad4f504aefbeb70c061e60cff10d153 Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Fri, 10 Jul 2020 10:56:28 -0400 Subject: [PATCH 021/771] [fix-irreducible] Skip unreachable predecessors. Summary: - Skip unreachable predecessors during header detection in SCC. Those unreachable blocks would be generated in the switch lowering pass in the corner cases or other frontends. Even though they could be removed through the CFG simplification, we should skip them during header detection. Reviewers: sameerds Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D83562 --- llvm/lib/Transforms/Utils/FixIrreducible.cpp | 3 +++ .../Transforms/FixIrreducible/unreachable.ll | 24 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 llvm/test/Transforms/FixIrreducible/unreachable.ll diff --git a/llvm/lib/Transforms/Utils/FixIrreducible.cpp b/llvm/lib/Transforms/Utils/FixIrreducible.cpp index 510c033f64743..452463c9b6277 100644 --- a/llvm/lib/Transforms/Utils/FixIrreducible.cpp +++ b/llvm/lib/Transforms/Utils/FixIrreducible.cpp @@ -281,6 +281,9 @@ static bool makeReducible(LoopInfo &LI, DominatorTree &DT, Graph &&G) { LLVM_DEBUG(dbgs() << "Found headers:"); for (auto BB : reverse(Blocks)) { for (const auto P : predecessors(BB)) { + // Skip unreachable predecessors. + if (!DT.isReachableFromEntry(P)) + continue; if (!Blocks.count(P)) { LLVM_DEBUG(dbgs() << " " << BB->getName()); Headers.insert(BB); diff --git a/llvm/test/Transforms/FixIrreducible/unreachable.ll b/llvm/test/Transforms/FixIrreducible/unreachable.ll new file mode 100644 index 0000000000000..71cd81e01953e --- /dev/null +++ b/llvm/test/Transforms/FixIrreducible/unreachable.ll @@ -0,0 +1,24 @@ +; RUN: opt %s -fix-irreducible -S -o - | FileCheck %s + +; CHECK-LABEL: @unreachable( +; CHECK: entry: +; CHECK-NOT: irr.guard: +define void @unreachable(i32 %n) { +entry: + br label %loop.body + +loop.body: + br label %inner.block + +unreachable.block: + br label %inner.block + +inner.block: + br i1 undef, label %loop.exit, label %loop.latch + +loop.latch: + br label %loop.body + +loop.exit: + ret void +} From 81db614411bdc8f95e5b7e2acaf551507eb7201b Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Sat, 11 Jul 2020 10:09:09 -0400 Subject: [PATCH 022/771] Fix `-Wunused-variable` warnings. NFC. --- llvm/lib/Transforms/IPO/OpenMPOpt.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp index f25e95466407d..2a3b2abf61762 100644 --- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp +++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp @@ -1043,12 +1043,12 @@ bool OpenMPOpt::rewriteDeviceCodeStateMachine() { return; } - if (auto *Cmp = dyn_cast(U.getUser())) { + if (isa(U.getUser())) { ToBeReplacedStateMachineUses.push_back(&U); return; } - if (CallInst *CI = OpenMPOpt::getCallIfRegularCall( - *U.getUser(), &KernelPrepareParallelRFI)) { + if (OpenMPOpt::getCallIfRegularCall(*U.getUser(), + &KernelPrepareParallelRFI)) { ToBeReplacedStateMachineUses.push_back(&U); return; } From 102828249c8ec9ab43ee84f496274f2853ed899c Mon Sep 17 00:00:00 2001 From: Yash Jain Date: Sat, 11 Jul 2020 20:54:18 +0530 Subject: [PATCH 023/771] [MLIR] Parallelize affine.for op to 1-D affine.parallel op Introduce pass to convert parallel affine.for op into 1-D affine.parallel op. Run using --affine-parallelize. Removes test-detect-parallel: pass for checking parallel affine.for ops. Signed-off-by: Yash Jain Differential Revision: https://reviews.llvm.org/D83193 --- mlir/include/mlir/Dialect/Affine/Passes.h | 4 + mlir/include/mlir/Dialect/Affine/Passes.td | 5 + mlir/include/mlir/Dialect/Affine/Utils.h | 7 ++ .../Affine/Transforms/AffineParallelize.cpp | 50 ++++++++ .../Dialect/Affine/Transforms/CMakeLists.txt | 2 + mlir/lib/Dialect/Affine/Utils/Utils.cpp | 15 +++ .../Dialect/Affine/parallelism-detection.mlir | 47 ------- mlir/test/Dialect/Affine/parallelize.mlir | 118 ++++++++++++++++++ mlir/test/lib/Dialect/Affine/CMakeLists.txt | 1 - .../Affine/TestParallelismDetection.cpp | 47 ------- mlir/tools/mlir-opt/mlir-opt.cpp | 2 - 11 files changed, 201 insertions(+), 97 deletions(-) create mode 100644 mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp delete mode 100644 mlir/test/Dialect/Affine/parallelism-detection.mlir create mode 100644 mlir/test/Dialect/Affine/parallelize.mlir delete mode 100644 mlir/test/lib/Dialect/Affine/TestParallelismDetection.cpp diff --git a/mlir/include/mlir/Dialect/Affine/Passes.h b/mlir/include/mlir/Dialect/Affine/Passes.h index 0d7c3be240c99..18b3b790338d8 100644 --- a/mlir/include/mlir/Dialect/Affine/Passes.h +++ b/mlir/include/mlir/Dialect/Affine/Passes.h @@ -36,6 +36,10 @@ std::unique_ptr> createSimplifyAffineStructuresPass(); std::unique_ptr> createAffineLoopInvariantCodeMotionPass(); +/// Creates a pass to convert all parallel affine.for's into 1-d affine.parallel +/// ops. +std::unique_ptr> createAffineParallelizePass(); + /// Performs packing (or explicit copying) of accessed memref regions into /// buffers in the specified faster memory space through either pointwise copies /// or DMA operations. diff --git a/mlir/include/mlir/Dialect/Affine/Passes.td b/mlir/include/mlir/Dialect/Affine/Passes.td index 06e0920413a95..810640058155f 100644 --- a/mlir/include/mlir/Dialect/Affine/Passes.td +++ b/mlir/include/mlir/Dialect/Affine/Passes.td @@ -112,6 +112,11 @@ def AffineVectorize : FunctionPass<"affine-super-vectorize"> { ]; } +def AffineParallelize : FunctionPass<"affine-parallelize"> { + let summary = "Convert affine.for ops into 1-D affine.parallel"; + let constructor = "mlir::createAffineParallelizePass()"; +} + def SimplifyAffineStructures : FunctionPass<"simplify-affine-structures"> { let summary = "Simplify affine expressions in maps/sets and normalize " "memrefs"; diff --git a/mlir/include/mlir/Dialect/Affine/Utils.h b/mlir/include/mlir/Dialect/Affine/Utils.h index a2c0211b301e3..19df93f760f5e 100644 --- a/mlir/include/mlir/Dialect/Affine/Utils.h +++ b/mlir/include/mlir/Dialect/Affine/Utils.h @@ -15,9 +15,16 @@ namespace mlir { +class AffineForOp; class AffineIfOp; +class AffineParallelOp; struct LogicalResult; +/// Replaces parallel affine.for op with 1-d affine.parallel op. +/// mlir::isLoopParallel detect the parallel affine.for ops. +/// There is no cost model currently used to drive this parallelization. +void affineParallelize(AffineForOp forOp); + /// Hoists out affine.if/else to as high as possible, i.e., past all invariant /// affine.fors/parallel's. Returns success if any hoisting happened; folded` is /// set to true if the op was folded or erased. This hoisting could lead to diff --git a/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp b/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp new file mode 100644 index 0000000000000..b3651e2022458 --- /dev/null +++ b/mlir/lib/Dialect/Affine/Transforms/AffineParallelize.cpp @@ -0,0 +1,50 @@ +//===- AffineParallelize.cpp - Affineparallelize Pass---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a parallelizer for affine loop nests that is able to +// perform inner or outer loop parallelization. +// +//===----------------------------------------------------------------------===// + +#include "PassDetail.h" +#include "mlir/Analysis/AffineStructures.h" +#include "mlir/Analysis/LoopAnalysis.h" +#include "mlir/Analysis/Utils.h" +#include "mlir/Dialect/Affine/IR/AffineOps.h" +#include "mlir/Dialect/Affine/IR/AffineValueMap.h" +#include "mlir/Dialect/Affine/Passes.h" +#include "mlir/Dialect/Affine/Passes.h.inc" +#include "mlir/Dialect/Affine/Utils.h" +#include "mlir/Transforms/LoopUtils.h" +#include "llvm/Support/Debug.h" + +#define DEBUG_TYPE "affine-parallel" + +using namespace mlir; + +namespace { +/// Convert all parallel affine.for op into 1-D affine.parallel op. +struct AffineParallelize : public AffineParallelizeBase { + void runOnFunction() override; +}; +} // namespace + +void AffineParallelize::runOnFunction() { + FuncOp f = getFunction(); + SmallVector parallelizableLoops; + f.walk([&](AffineForOp loop) { + if (isLoopParallel(loop)) + parallelizableLoops.push_back(loop); + }); + for (AffineForOp loop : parallelizableLoops) + affineParallelize(loop); +} + +std::unique_ptr> mlir::createAffineParallelizePass() { + return std::make_unique(); +} diff --git a/mlir/lib/Dialect/Affine/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Affine/Transforms/CMakeLists.txt index 0098c3e210914..dddcc93adf0d6 100644 --- a/mlir/lib/Dialect/Affine/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/Affine/Transforms/CMakeLists.txt @@ -1,6 +1,7 @@ add_mlir_dialect_library(MLIRAffineTransforms AffineDataCopyGeneration.cpp AffineLoopInvariantCodeMotion.cpp + AffineParallelize.cpp LoopTiling.cpp LoopUnroll.cpp LoopUnrollAndJam.cpp @@ -17,6 +18,7 @@ add_mlir_dialect_library(MLIRAffineTransforms LINK_LIBS PUBLIC MLIRAffineOps + MLIRAffineUtils MLIREDSC MLIRIR MLIRPass diff --git a/mlir/lib/Dialect/Affine/Utils/Utils.cpp b/mlir/lib/Dialect/Affine/Utils/Utils.cpp index 57e6bce90844b..39e9cbc61e961 100644 --- a/mlir/lib/Dialect/Affine/Utils/Utils.cpp +++ b/mlir/lib/Dialect/Affine/Utils/Utils.cpp @@ -129,6 +129,21 @@ static AffineIfOp hoistAffineIfOp(AffineIfOp ifOp, Operation *hoistOverOp) { return hoistedIfOp; } +/// Replace affine.for with a 1-d affine.parallel and clone the former's body +/// into the latter while remapping values. +void mlir::affineParallelize(AffineForOp forOp) { + Location loc = forOp.getLoc(); + OpBuilder outsideBuilder(forOp); + // Creating empty 1-D affine.parallel op. + AffineParallelOp newPloop = outsideBuilder.create( + loc, llvm::None, llvm::None, forOp.getLowerBoundMap(), + forOp.getLowerBoundOperands(), forOp.getUpperBoundMap(), + forOp.getUpperBoundOperands()); + // Steal the body of the old affine for op and erase it. + newPloop.region().takeBody(forOp.region()); + forOp.erase(); +} + // Returns success if any hoisting happened. LogicalResult mlir::hoistAffineIfOp(AffineIfOp ifOp, bool *folded) { // Bail out early if the ifOp returns a result. TODO: Consider how to diff --git a/mlir/test/Dialect/Affine/parallelism-detection.mlir b/mlir/test/Dialect/Affine/parallelism-detection.mlir deleted file mode 100644 index 0788e6f8fb208..0000000000000 --- a/mlir/test/Dialect/Affine/parallelism-detection.mlir +++ /dev/null @@ -1,47 +0,0 @@ -// RUN: mlir-opt -allow-unregistered-dialect %s -test-detect-parallel -split-input-file -verify-diagnostics | FileCheck %s - -// CHECK-LABEL: func @loop_nest_3d_outer_two_parallel -func @loop_nest_3d_outer_two_parallel(%N : index) { - %0 = alloc() : memref<1024 x 1024 x vector<64xf32>> - %1 = alloc() : memref<1024 x 1024 x vector<64xf32>> - %2 = alloc() : memref<1024 x 1024 x vector<64xf32>> - affine.for %i = 0 to %N { - // expected-remark@-1 {{parallel loop}} - affine.for %j = 0 to %N { - // expected-remark@-1 {{parallel loop}} - affine.for %k = 0 to %N { - // expected-remark@-1 {{sequential loop}} - %5 = affine.load %0[%i, %k] : memref<1024x1024xvector<64xf32>> - %6 = affine.load %1[%k, %j] : memref<1024x1024xvector<64xf32>> - %7 = affine.load %2[%i, %j] : memref<1024x1024xvector<64xf32>> - %8 = mulf %5, %6 : vector<64xf32> - %9 = addf %7, %8 : vector<64xf32> - affine.store %9, %2[%i, %j] : memref<1024x1024xvector<64xf32>> - } - } - } - return -} - -// ----- - -// CHECK-LABEL: unknown_op_conservative -func @unknown_op_conservative() { - affine.for %i = 0 to 10 { - // expected-remark@-1 {{sequential loop}} - "unknown"() : () -> () - } - return -} - -// ----- - -// CHECK-LABEL: non_affine_load -func @non_affine_load() { - %0 = alloc() : memref<100 x f32> - affine.for %i = 0 to 100 { - // expected-remark@-1 {{sequential loop}} - load %0[%i] : memref<100 x f32> - } - return -} diff --git a/mlir/test/Dialect/Affine/parallelize.mlir b/mlir/test/Dialect/Affine/parallelize.mlir new file mode 100644 index 0000000000000..5287628185c5b --- /dev/null +++ b/mlir/test/Dialect/Affine/parallelize.mlir @@ -0,0 +1,118 @@ +// RUN: mlir-opt %s -allow-unregistered-dialect -affine-parallelize| FileCheck %s + +// For multiple nested for-loops. +// CHECK-DAG: [[MAP5:#map[0-9]+]] = affine_map<(d0, d1, d2, d3, d4, d5, d6, d7) -> (d0 + d1, d2 * 2 + d3, d4 * 2 + d5, d6 + d7)> +// CHECK-LABEL: func @reduce_window_max() { +func @reduce_window_max() { + %cst = constant 0.000000e+00 : f32 + %0 = alloc() : memref<1x8x8x64xf32> + %1 = alloc() : memref<1x18x18x64xf32> + affine.for %arg0 = 0 to 1 { + affine.for %arg1 = 0 to 8 { + affine.for %arg2 = 0 to 8 { + affine.for %arg3 = 0 to 64 { + affine.store %cst, %0[%arg0, %arg1, %arg2, %arg3] : memref<1x8x8x64xf32> + } + } + } + } + affine.for %arg0 = 0 to 1 { + affine.for %arg1 = 0 to 8 { + affine.for %arg2 = 0 to 8 { + affine.for %arg3 = 0 to 64 { + affine.for %arg4 = 0 to 1 { + affine.for %arg5 = 0 to 3 { + affine.for %arg6 = 0 to 3 { + affine.for %arg7 = 0 to 1 { + %2 = affine.load %0[%arg0, %arg1, %arg2, %arg3] : memref<1x8x8x64xf32> + %3 = affine.load %1[%arg0 + %arg4, %arg1 * 2 + %arg5, %arg2 * 2 + %arg6, %arg3 + %arg7] : memref<1x18x18x64xf32> + %4 = cmpf "ogt", %2, %3 : f32 + %5 = select %4, %2, %3 : f32 + affine.store %5, %0[%arg0, %arg1, %arg2, %arg3] : memref<1x8x8x64xf32> + } + } + } + } + } + } + } + } + return +} + +// CHECK: %[[cst:.*]] = constant 0.000000e+00 : f32 +// CHECK: %[[v0:.*]] = alloc() : memref<1x8x8x64xf32> +// CHECK: %[[v1:.*]] = alloc() : memref<1x18x18x64xf32> +// CHECK: affine.parallel (%[[arg0:.*]]) = (0) to (1) { +// CHECK: affine.parallel (%[[arg1:.*]]) = (0) to (8) { +// CHECK: affine.parallel (%[[arg2:.*]]) = (0) to (8) { +// CHECK: affine.parallel (%[[arg3:.*]]) = (0) to (64) { +// CHECK: affine.store %[[cst]], %[[v0]][%[[arg0]], %[[arg1]], %[[arg2]], %[[arg3]]] : memref<1x8x8x64xf32> +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: affine.parallel (%[[a0:.*]]) = (0) to (1) { +// CHECK: affine.parallel (%[[a1:.*]]) = (0) to (8) { +// CHECK: affine.parallel (%[[a2:.*]]) = (0) to (8) { +// CHECK: affine.parallel (%[[a3:.*]]) = (0) to (64) { +// CHECK: affine.parallel (%[[a4:.*]]) = (0) to (1) { +// CHECK: affine.for %[[a5:.*]] = 0 to 3 { +// CHECK: affine.for %[[a6:.*]] = 0 to 3 { +// CHECK: affine.parallel (%[[a7:.*]]) = (0) to (1) { +// CHECK: %[[lhs:.*]] = affine.load %[[v0]][%[[a0]], %[[a1]], %[[a2]], %[[a3]]] : memref<1x8x8x64xf32> +// CHECK: %[[rhs:.*]] = affine.load %[[v1]][%[[a0]] + %[[a4]], %[[a1]] * 2 + %[[a5]], %[[a2]] * 2 + %[[a6]], %[[a3]] + %[[a7]]] : memref<1x18x18x64xf32> +// CHECK: %[[res:.*]] = cmpf "ogt", %[[lhs]], %[[rhs]] : f32 +// CHECK: %[[sel:.*]] = select %[[res]], %[[lhs]], %[[rhs]] : f32 +// CHECK: affine.store %[[sel]], %[[v0]][%[[a0]], %[[a1]], %[[a2]], %[[a3]]] : memref<1x8x8x64xf32> +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: } +// CHECK: } + +func @loop_nest_3d_outer_two_parallel(%N : index) { + %0 = alloc() : memref<1024 x 1024 x vector<64xf32>> + %1 = alloc() : memref<1024 x 1024 x vector<64xf32>> + %2 = alloc() : memref<1024 x 1024 x vector<64xf32>> + affine.for %i = 0 to %N { + affine.for %j = 0 to %N { + %7 = affine.load %2[%i, %j] : memref<1024x1024xvector<64xf32>> + affine.for %k = 0 to %N { + %5 = affine.load %0[%i, %k] : memref<1024x1024xvector<64xf32>> + %6 = affine.load %1[%k, %j] : memref<1024x1024xvector<64xf32>> + %8 = mulf %5, %6 : vector<64xf32> + %9 = addf %7, %8 : vector<64xf32> + affine.store %9, %2[%i, %j] : memref<1024x1024xvector<64xf32>> + } + } + } + return +} + +// CHECK: affine.parallel (%[[arg1:.*]]) = (0) to (symbol(%arg0)) { +// CHECK-NEXT: affine.parallel (%[[arg2:.*]]) = (0) to (symbol(%arg0)) { +// CHECK: affine.for %[[arg3:.*]] = 0 to %arg0 { + +// CHECK-LABEL: unknown_op_conservative +func @unknown_op_conservative() { + affine.for %i = 0 to 10 { +// CHECK: affine.for %[[arg1:.*]] = 0 to 10 { + "unknown"() : () -> () + } + return +} + +// CHECK-LABEL: non_affine_load +func @non_affine_load() { + %0 = alloc() : memref<100 x f32> + affine.for %i = 0 to 100 { +// CHECK: affine.for %{{.*}} = 0 to 100 { + load %0[%i] : memref<100 x f32> + } + return +} diff --git a/mlir/test/lib/Dialect/Affine/CMakeLists.txt b/mlir/test/lib/Dialect/Affine/CMakeLists.txt index 68a0b06e0e318..3d08fed788e2e 100644 --- a/mlir/test/lib/Dialect/Affine/CMakeLists.txt +++ b/mlir/test/lib/Dialect/Affine/CMakeLists.txt @@ -3,7 +3,6 @@ add_mlir_library(MLIRAffineTransformsTestPasses TestAffineDataCopy.cpp TestAffineLoopUnswitching.cpp TestLoopPermutation.cpp - TestParallelismDetection.cpp TestVectorizationUtils.cpp EXCLUDE_FROM_LIBMLIR diff --git a/mlir/test/lib/Dialect/Affine/TestParallelismDetection.cpp b/mlir/test/lib/Dialect/Affine/TestParallelismDetection.cpp deleted file mode 100644 index b19e260316939..0000000000000 --- a/mlir/test/lib/Dialect/Affine/TestParallelismDetection.cpp +++ /dev/null @@ -1,47 +0,0 @@ -//===- ParallelismDetection.cpp - Parallelism Detection pass ------------*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements a pass to detect parallel affine 'affine.for' ops. -// -//===----------------------------------------------------------------------===// - -#include "mlir/Analysis/Utils.h" -#include "mlir/Dialect/Affine/IR/AffineOps.h" -#include "mlir/IR/Builders.h" -#include "mlir/Pass/Pass.h" - -using namespace mlir; - -namespace { - -struct TestParallelismDetection - : public PassWrapper { - void runOnFunction() override; -}; - -} // end anonymous namespace - -// Walks the function and emits a note for all 'affine.for' ops detected as -// parallel. -void TestParallelismDetection::runOnFunction() { - FuncOp f = getFunction(); - OpBuilder b(f.getBody()); - f.walk([&](AffineForOp forOp) { - if (isLoopParallel(forOp)) - forOp.emitRemark("parallel loop"); - else - forOp.emitRemark("sequential loop"); - }); -} - -namespace mlir { -void registerTestParallelismDetection() { - PassRegistration pass( - "test-detect-parallel", "Test parallelism detection "); -} -} // namespace mlir diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp index 0ce5fac1223c6..f749c7ad98adf 100644 --- a/mlir/tools/mlir-opt/mlir-opt.cpp +++ b/mlir/tools/mlir-opt/mlir-opt.cpp @@ -62,7 +62,6 @@ void registerTestMatchers(); void registerTestMemRefDependenceCheck(); void registerTestMemRefStrideCalculation(); void registerTestOpaqueLoc(); -void registerTestParallelismDetection(); void registerTestPreparationPassWithAllowedMemrefResults(); void registerTestReducer(); void registerTestGpuParallelLoopMappingPass(); @@ -138,7 +137,6 @@ void registerTestPasses() { registerTestMemRefDependenceCheck(); registerTestMemRefStrideCalculation(); registerTestOpaqueLoc(); - registerTestParallelismDetection(); registerTestPreparationPassWithAllowedMemrefResults(); registerTestReducer(); registerTestGpuParallelLoopMappingPass(); From 6e42a417bacbfd5a1f58b0ccb7c9b34ff9e54523 Mon Sep 17 00:00:00 2001 From: Valentin Clement Date: Sat, 11 Jul 2020 12:42:05 -0400 Subject: [PATCH 024/771] [flang][openmp] Check clauses allowed semantic with tablegen generated map Summary: This patch is enabling the generation of clauses enum sets for semantics check in Flang through tablegen. Enum sets and directive - sets map is generated by the new tablegen infrsatructure for OpenMP and other directive languages. The semantic checks for OpenMP are modified to use this newly generated map. Reviewers: DavidTruby, sscalpone, kiranchandramohan, ichoyjx, jdoerfert Reviewed By: DavidTruby, ichoyjx Subscribers: mgorny, yaxunl, hiraditya, guansong, sstefan1, aaron.ballman, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D83326 --- flang/lib/Semantics/check-omp-structure.cpp | 494 +---------------- flang/lib/Semantics/check-omp-structure.h | 21 +- .../test/Semantics/omp-clause-validity01.f90 | 1 - .../llvm/Frontend/Directive/DirectiveBase.td | 6 + .../llvm/Frontend/OpenMP/CMakeLists.txt | 1 + llvm/include/llvm/Frontend/OpenMP/OMP.td | 506 +++++++++++------- llvm/test/TableGen/directive1.td | 55 ++ llvm/test/TableGen/directive2.td | 54 +- llvm/utils/TableGen/DirectiveEmitter.cpp | 222 +++++++- llvm/utils/TableGen/TableGen.cpp | 10 +- llvm/utils/TableGen/TableGenBackends.h | 1 + 11 files changed, 685 insertions(+), 686 deletions(-) diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index b4e86faffe195..a5f65bcbc8044 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -13,58 +13,6 @@ namespace Fortran::semantics { -static OmpClauseSet doAllowedClauses{llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate, llvm::omp::Clause::OMPC_lastprivate, - llvm::omp::Clause::OMPC_linear, llvm::omp::Clause::OMPC_reduction}; -static OmpClauseSet doAllowedOnceClauses{llvm::omp::Clause::OMPC_schedule, - llvm::omp::Clause::OMPC_collapse, llvm::omp::Clause::OMPC_ordered}; - -static OmpClauseSet simdAllowedClauses{llvm::omp::Clause::OMPC_linear, - llvm::omp::Clause::OMPC_aligned, llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_lastprivate, llvm::omp::Clause::OMPC_reduction}; -static OmpClauseSet simdAllowedOnceClauses{llvm::omp::Clause::OMPC_collapse, - llvm::omp::Clause::OMPC_safelen, llvm::omp::Clause::OMPC_simdlen}; - -static OmpClauseSet parallelAllowedClauses{llvm::omp::Clause::OMPC_default, - llvm::omp::Clause::OMPC_private, llvm::omp::Clause::OMPC_firstprivate, - llvm::omp::Clause::OMPC_shared, llvm::omp::Clause::OMPC_copyin, - llvm::omp::Clause::OMPC_reduction}; -static OmpClauseSet parallelAllowedOnceClauses{llvm::omp::Clause::OMPC_if, - llvm::omp::Clause::OMPC_num_threads, llvm::omp::Clause::OMPC_proc_bind}; - -static OmpClauseSet taskloopAllowedClauses{llvm::omp::Clause::OMPC_shared, - llvm::omp::Clause::OMPC_private, llvm::omp::Clause::OMPC_firstprivate, - llvm::omp::Clause::OMPC_lastprivate, llvm::omp::Clause::OMPC_default, - llvm::omp::Clause::OMPC_untied, llvm::omp::Clause::OMPC_mergeable, - llvm::omp::Clause::OMPC_nogroup}; -static OmpClauseSet taskloopAllowedOnceClauses{llvm::omp::Clause::OMPC_collapse, - llvm::omp::Clause::OMPC_if, llvm::omp::Clause::OMPC_final, - llvm::omp::Clause::OMPC_priority}; -static OmpClauseSet taskloopAllowedExclusiveClauses{ - llvm::omp::Clause::OMPC_grainsize, llvm::omp::Clause::OMPC_num_tasks}; - -static OmpClauseSet distributeAllowedClauses{llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate, llvm::omp::Clause::OMPC_lastprivate}; -static OmpClauseSet distributeAllowedOnceClauses{ - llvm::omp::Clause::OMPC_collapse, llvm::omp::Clause::OMPC_dist_schedule}; - -static OmpClauseSet targetAllowedClauses{llvm::omp::Clause::OMPC_if, - llvm::omp::Clause::OMPC_private, llvm::omp::Clause::OMPC_firstprivate, - llvm::omp::Clause::OMPC_map, llvm::omp::Clause::OMPC_is_device_ptr, - llvm::omp::Clause::OMPC_depend}; -static OmpClauseSet targetAllowedOnceClauses{llvm::omp::Clause::OMPC_device, - llvm::omp::Clause::OMPC_defaultmap, llvm::omp::Clause::OMPC_nowait}; - -static OmpClauseSet teamsAllowedClauses{llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate, llvm::omp::Clause::OMPC_shared, - llvm::omp::Clause::OMPC_reduction}; -static OmpClauseSet teamsAllowedOnceClauses{llvm::omp::Clause::OMPC_num_teams, - llvm::omp::Clause::OMPC_thread_limit, llvm::omp::Clause::OMPC_default}; - -static OmpClauseSet sectionsAllowedClauses{llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate, llvm::omp::Clause::OMPC_lastprivate, - llvm::omp::Clause::OMPC_reduction}; - std::string OmpStructureChecker::ContextDirectiveAsFortran() { auto dir = llvm::omp::getOpenMPDirectiveName(GetContext().directive).str(); std::transform(dir.begin(), dir.end(), dir.begin(), @@ -186,19 +134,18 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { CheckMatching(beginLoopDir, *endLoopDir); } - if (beginDir.v != llvm::omp::Directive::OMPD_do) - PushContext(beginDir.source, beginDir.v); + if (beginDir.v != llvm::omp::Directive::OMPD_do) { + PushContextAndClauseSets(beginDir.source, beginDir.v); + } else { + // 2.7.1 do-clause -> private-clause | + // firstprivate-clause | + // lastprivate-clause | + // linear-clause | + // reduction-clause | + // schedule-clause | + // collapse-clause | + // ordered-clause - switch (beginDir.v) { - // 2.7.1 do-clause -> private-clause | - // firstprivate-clause | - // lastprivate-clause | - // linear-clause | - // reduction-clause | - // schedule-clause | - // collapse-clause | - // ordered-clause - case llvm::omp::Directive::OMPD_do: { // nesting check HasInvalidWorksharingNesting(beginDir.source, {llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_sections, @@ -210,218 +157,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPLoopConstruct &x) { llvm::omp::Directive::OMPD_ordered, llvm::omp::Directive::OMPD_atomic, llvm::omp::Directive::OMPD_master}); - PushContext(beginDir.source, llvm::omp::Directive::OMPD_do); - SetContextAllowed(doAllowedClauses); - SetContextAllowedOnce(doAllowedOnceClauses); - } break; - - // 2.11.1 parallel-do-clause -> parallel-clause | - // do-clause - case llvm::omp::Directive::OMPD_parallel_do: { - SetContextAllowed(parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses | doAllowedOnceClauses); - } break; - - // 2.8.1 simd-clause -> safelen-clause | - // simdlen-clause | - // linear-clause | - // aligned-clause | - // private-clause | - // lastprivate-clause | - // reduction-clause | - // collapse-clause - case llvm::omp::Directive::OMPD_simd: { - SetContextAllowed(simdAllowedClauses); - SetContextAllowedOnce(simdAllowedOnceClauses); - } break; - - // 2.8.3 do-simd-clause -> do-clause | - // simd-clause - case llvm::omp::Directive::OMPD_do_simd: { - SetContextAllowed(doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(doAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.11.4 parallel-do-simd-clause -> parallel-clause | - // do-simd-clause - case llvm::omp::Directive::OMPD_parallel_do_simd: { - SetContextAllowed( - parallelAllowedClauses | doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses | doAllowedOnceClauses | - simdAllowedOnceClauses); - } break; - - // 2.9.2 taskloop-clause -> if-clause | - // shared-clause | - // private-clause | - // firstprivate-clause | - // lastprivate-clause | - // default-clause | - // grainsize-clause | - // num-tasks-clause | - // collapse-clause | - // final-clause | - // priority-clause | - // untied-clause | - // mergeable-clause | - // nogroup-clause - case llvm::omp::Directive::OMPD_taskloop: { - SetContextAllowed(taskloopAllowedClauses); - SetContextAllowedOnce(taskloopAllowedOnceClauses); - SetContextAllowedExclusive(taskloopAllowedExclusiveClauses); - } break; - - // 2.9.3 taskloop-simd-clause -> taskloop-clause | - // simd-clause - case llvm::omp::Directive::OMPD_taskloop_simd: { - SetContextAllowed((taskloopAllowedClauses | simdAllowedClauses) - - llvm::omp::Clause::OMPC_reduction); - SetContextAllowedOnce(taskloopAllowedOnceClauses | simdAllowedOnceClauses); - SetContextAllowedExclusive(taskloopAllowedExclusiveClauses); - } break; - - // 2.10.8 distribute-clause -> private-clause | - // firstprivate-clause | - // lastprivate-clause | - // collapse-clause | - // dist-schedule-clause - case llvm::omp::Directive::OMPD_distribute: { - SetContextAllowed(distributeAllowedClauses); - SetContextAllowedOnce(distributeAllowedOnceClauses); - } break; - - // 2.10.9 distribute-simd-clause -> distribute-clause | - // simd-clause - case llvm::omp::Directive::OMPD_distribute_simd: { - SetContextAllowed(distributeAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce( - distributeAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.10.10 distribute-parallel-do-clause -> distribute-clause | - // parallel-do-clause - case llvm::omp::Directive::OMPD_distribute_parallel_do: { - SetContextAllowed( - distributeAllowedClauses | parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce(distributeAllowedOnceClauses | - parallelAllowedOnceClauses | doAllowedOnceClauses); - } break; - - // 2.10.11 distribute-parallel-do-simd-clause -> distribute-clause | - // parallel-do-simd-clause - case llvm::omp::Directive::OMPD_distribute_parallel_do_simd: { - SetContextAllowed(distributeAllowedClauses | parallelAllowedClauses | - doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(distributeAllowedOnceClauses | - parallelAllowedOnceClauses | doAllowedOnceClauses | simdAllowedClauses); - } break; - - // 2.11.6 target-parallel-do-clause -> target-clause | - // parallel-do-clause - case llvm::omp::Directive::OMPD_target_parallel_do: { - SetContextAllowed( - targetAllowedClauses | parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce( - (targetAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses) - - llvm::omp::Clause::OMPC_nowait); - } break; - - // 2.11.7 target-parallel-do-simd-clause -> target-clause | - // parallel-do-simd-clause - case llvm::omp::Directive::OMPD_target_parallel_do_simd: { - SetContextAllowed(targetAllowedClauses | parallelAllowedClauses | - doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce( - (targetAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses | simdAllowedOnceClauses) - - llvm::omp::Clause::OMPC_nowait); - } break; - - // 2.11.8 target-simd-clause -> target-clause | - // simd-clause - case llvm::omp::Directive::OMPD_target_simd: { - SetContextAllowed(targetAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.11.10 teams-distribute-clause -> teams-clause | - // distribute-clause - case llvm::omp::Directive::OMPD_teams_distribute: { - SetContextAllowed(teamsAllowedClauses | distributeAllowedClauses); - SetContextAllowedOnce( - teamsAllowedOnceClauses | distributeAllowedOnceClauses); - } break; - - // 2.11.11 teams-distribute-simd-clause -> teams-clause | - // distribute-simd-clause - case llvm::omp::Directive::OMPD_teams_distribute_simd: { - SetContextAllowed( - teamsAllowedClauses | distributeAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(teamsAllowedOnceClauses | - distributeAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.11.12 target-teams-distribute-clause -> target-clause | - // teams-distribute-clause - case llvm::omp::Directive::OMPD_target_teams_distribute: { - SetContextAllowed( - targetAllowedClauses | teamsAllowedClauses | distributeAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | teamsAllowedOnceClauses | - distributeAllowedOnceClauses); - } break; - - // 2.11.13 target-teams-distribute-simd-clause -> target-clause | - // teams-distribute-simd-clause - case llvm::omp::Directive::OMPD_target_teams_distribute_simd: { - SetContextAllowed(targetAllowedClauses | teamsAllowedClauses | - distributeAllowedClauses | simdAllowedClauses); - SetContextAllowed(targetAllowedOnceClauses | teamsAllowedOnceClauses | - distributeAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - // 2.11.14 teams-distribute-parallel-do-clause -> teams-clause | - // distribute-parallel-do-clause - case llvm::omp::Directive::OMPD_teams_distribute_parallel_do: { - SetContextAllowed(teamsAllowedClauses | distributeAllowedClauses | - parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce(teamsAllowedOnceClauses | - distributeAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses); - } break; - - // 2.11.15 target-teams-distribute-parallel-do-clause -> target-clause | - // teams-distribute-parallel-do-clause - case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do: { - SetContextAllowed(targetAllowedClauses | teamsAllowedClauses | - distributeAllowedClauses | parallelAllowedClauses | doAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | teamsAllowedOnceClauses | - distributeAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses); - } break; - - // 2.11.16 teams-distribute-parallel-do-clause -> teams-clause | - // distribute-parallel-do-simd-clause - case llvm::omp::Directive::OMPD_teams_distribute_parallel_do_simd: { - SetContextAllowed(teamsAllowedClauses | distributeAllowedClauses | - parallelAllowedClauses | doAllowedClauses | simdAllowedClauses); - SetContextAllowedOnce(teamsAllowedOnceClauses | - distributeAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd: { - SetContextAllowed(targetAllowedClauses | teamsAllowedClauses | - distributeAllowedClauses | parallelAllowedClauses | doAllowedClauses | - simdAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | teamsAllowedOnceClauses | - distributeAllowedOnceClauses | parallelAllowedOnceClauses | - doAllowedOnceClauses | simdAllowedOnceClauses); - } break; - - default: - // TODO others - break; + PushContextAndClauseSets(beginDir.source, llvm::omp::Directive::OMPD_do); } } @@ -436,12 +172,8 @@ void OmpStructureChecker::Enter(const parser::OmpEndLoopDirective &x) { // 2.7.1 end-do -> END DO [nowait-clause] // 2.8.3 end-do-simd -> END DO SIMD [nowait-clause] case llvm::omp::Directive::OMPD_do: - SetContextDirectiveEnum(llvm::omp::Directive::OMPD_end_do); - SetContextAllowed(OmpClauseSet{llvm::omp::Clause::OMPC_nowait}); - break; case llvm::omp::Directive::OMPD_do_simd: - SetContextDirectiveEnum(llvm::omp::Directive::OMPD_end_do_simd); - SetContextAllowed(OmpClauseSet{llvm::omp::Clause::OMPC_nowait}); + SetClauseSets(dir.v); break; default: // no clauses are allowed @@ -455,112 +187,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) { const auto &beginDir{ CheckMatching(beginBlockDir, endBlockDir)}; - PushContext(beginDir.source, beginDir.v); - switch (beginDir.v) { - // 2.5 parallel-clause -> if-clause | - // num-threads-clause | - // default-clause | - // private-clause | - // firstprivate-clause | - // shared-clause | - // copyin-clause | - // reduction-clause | - // proc-bind-clause - case llvm::omp::Directive::OMPD_parallel: { - // reserve for nesting check - SetContextAllowed(parallelAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses); - } break; - // 2.7.3 single-clause -> private-clause | - // firstprivate-clause - case llvm::omp::Directive::OMPD_single: - SetContextAllowed({llvm::omp::Clause::OMPC_private, - llvm::omp::Clause::OMPC_firstprivate}); - break; - // 2.7.4 workshare (no clauses are allowed) - case llvm::omp::Directive::OMPD_workshare: - break; - // 2.11.3 parallel-workshare-clause -> parallel-clause - case llvm::omp::Directive::OMPD_parallel_workshare: { - SetContextAllowed(parallelAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses); - } break; - // 2.9.1 task-clause -> if-clause | - // final-clause | - // untied-clause | - // default-clause | - // mergeable-clause | - // private-clause | - // firstprivate-clause | - // shared-clause | - // depend-clause | - // priority-clause - case llvm::omp::Directive::OMPD_task: { - OmpClauseSet allowed{llvm::omp::Clause::OMPC_untied, - llvm::omp::Clause::OMPC_default, llvm::omp::Clause::OMPC_mergeable, - llvm::omp::Clause::OMPC_private, llvm::omp::Clause::OMPC_firstprivate, - llvm::omp::Clause::OMPC_shared, llvm::omp::Clause::OMPC_depend}; - SetContextAllowed(allowed); - OmpClauseSet allowedOnce{llvm::omp::Clause::OMPC_if, - llvm::omp::Clause::OMPC_final, llvm::omp::Clause::OMPC_priority}; - SetContextAllowedOnce(allowedOnce); - } break; - // 2.10.4 target-clause -> if-clause | - // device-clause | - // private-clause | - // firstprivate-clause | - // map-clause | - // is-device-ptr-clause | - // defaultmap-clause | - // nowait-clause | - // depend-clause - case llvm::omp::Directive::OMPD_target: { - SetContextAllowed(targetAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses); - } break; - // 2.10.7 teams-clause -> num-teams-clause | - // thread-limit-clause | - // default-clause | - // private-clause | - // firstprivate-clause | - // shared-clause | - // reduction-clause - case llvm::omp::Directive::OMPD_teams: { - SetContextAllowed(teamsAllowedClauses); - SetContextAllowedOnce(teamsAllowedOnceClauses); - } break; - // 2.11.9 target-teams -> target-clause | - // teams-clause - case llvm::omp::Directive::OMPD_target_teams: { - SetContextAllowed(targetAllowedClauses | teamsAllowedClauses); - SetContextAllowedOnce(targetAllowedOnceClauses | teamsAllowedOnceClauses); - } break; - // 2.10.1 target-data-clause -> if-clause | - // device-clause | - // map-clause | - // use-device-ptr-clause - case llvm::omp::Directive::OMPD_target_data: { - OmpClauseSet allowed{llvm::omp::Clause::OMPC_if, - llvm::omp::Clause::OMPC_map, llvm::omp::Clause::OMPC_use_device_ptr}; - SetContextAllowed(allowed); - SetContextAllowedOnce({llvm::omp::Clause::OMPC_device}); - SetContextRequired({llvm::omp::Clause::OMPC_map}); - } break; - // 2.13.1 master (no clauses are allowed) - case llvm::omp::Directive::OMPD_master: - break; - // 2.11.5 target-parallel-clause -> target-clause | - // parallel-clause - case llvm::omp::Directive::OMPD_target_parallel: { - SetContextAllowed((targetAllowedClauses | parallelAllowedClauses) - - llvm::omp::Clause::OMPC_copyin); - SetContextAllowedOnce( - targetAllowedOnceClauses | parallelAllowedOnceClauses); - } break; - default: - // TODO others - break; - } + PushContextAndClauseSets(beginDir.source, beginDir.v); } void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) { @@ -574,25 +201,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) { const auto &beginDir{CheckMatching( beginSectionsDir, endSectionsDir)}; - PushContext(beginDir.source, beginDir.v); - switch (beginDir.v) { - // 2.7.2 sections-clause -> private-clause | - // firstprivate-clause | - // lastprivate-clause | - // reduction-clause - case llvm::omp::Directive::OMPD_sections: { - SetContextAllowed(sectionsAllowedClauses); - } break; - // 2.11.2 -> parallel-sections-clause -> parallel-clause | - // sections-clause - case llvm::omp::Directive::OMPD_parallel_sections: { - SetContextAllowed(parallelAllowedClauses | sectionsAllowedClauses); - SetContextAllowedOnce(parallelAllowedOnceClauses); - } break; - default: - // TODO others - break; - } + PushContextAndClauseSets(beginDir.source, beginDir.v); } void OmpStructureChecker::Leave(const parser::OpenMPSectionsConstruct &) { @@ -616,19 +225,7 @@ void OmpStructureChecker::Enter(const parser::OmpEndSectionsDirective &x) { void OmpStructureChecker::Enter(const parser::OpenMPDeclareSimdConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, llvm::omp::Directive::OMPD_declare_simd); - // 2.8.2 declare-simd-clause -> simdlen-clause | - // linear-clause | - // aligned-clause | - // uniform-clause | - // inbranch-clause | - // notinbranch-clause - OmpClauseSet allowed{llvm::omp::Clause::OMPC_linear, - llvm::omp::Clause::OMPC_aligned, llvm::omp::Clause::OMPC_uniform}; - SetContextAllowed(allowed); - SetContextAllowedOnce({llvm::omp::Clause::OMPC_simdlen}); - SetContextAllowedExclusive( - {llvm::omp::Clause::OMPC_inbranch, llvm::omp::Clause::OMPC_notinbranch}); + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_declare_simd); } void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) { @@ -652,57 +249,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &) { void OmpStructureChecker::Enter( const parser::OpenMPSimpleStandaloneConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, dir.v); - switch (dir.v) { - case llvm::omp::Directive::OMPD_barrier: { - // 2.13.3 barrier - } break; - case llvm::omp::Directive::OMPD_taskwait: { - // 2.13.4 taskwait - } break; - case llvm::omp::Directive::OMPD_taskyield: { - // 2.9.4 taskyield - } break; - case llvm::omp::Directive::OMPD_target_enter_data: { - // 2.10.2 target-enter-data-clause -> if-clause | - // device-clause | - // map-clause | - // depend-clause | - // nowait-clause - OmpClauseSet allowed{llvm::omp::Clause::OMPC_map, - llvm::omp::Clause::OMPC_depend, llvm::omp::Clause::OMPC_nowait}; - SetContextAllowed(allowed); - OmpClauseSet allowedOnce{ - llvm::omp::Clause::OMPC_device, llvm::omp::Clause::OMPC_if}; - SetContextAllowedOnce(allowedOnce); - SetContextRequired({llvm::omp::Clause::OMPC_map}); - } break; - case llvm::omp::Directive::OMPD_target_exit_data: { - // 2.10.3 target-enter-data-clause -> if-clause | - // device-clause | - // map-clause | - // depend-clause | - // nowait-clause - OmpClauseSet allowed{llvm::omp::Clause::OMPC_map, - llvm::omp::Clause::OMPC_depend, llvm::omp::Clause::OMPC_nowait}; - SetContextAllowed(allowed); - OmpClauseSet allowedOnce{ - llvm::omp::Clause::OMPC_device, llvm::omp::Clause::OMPC_if}; - SetContextAllowedOnce(allowedOnce); - SetContextRequired({llvm::omp::Clause::OMPC_map}); - } break; - case llvm::omp::Directive::OMPD_target_update: { - // 2.10.5 target-update - } break; - case llvm::omp::Directive::OMPD_ordered: { - // 2.13.8 ordered-construct-clause -> depend-clause - OmpClauseSet allowed{llvm::omp::Clause::OMPC_depend}; - SetContextAllowed(allowed); - } break; - default: - // TODO others - break; - } + PushContextAndClauseSets(dir.source, dir.v); } void OmpStructureChecker::Leave( @@ -712,7 +259,7 @@ void OmpStructureChecker::Leave( void OmpStructureChecker::Enter(const parser::OpenMPFlushConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, llvm::omp::Directive::OMPD_flush); + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_flush); } void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) { @@ -721,7 +268,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &) { void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, llvm::omp::Directive::OMPD_cancel); + PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_cancel); } void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) { @@ -731,7 +278,8 @@ void OmpStructureChecker::Leave(const parser::OpenMPCancelConstruct &) { void OmpStructureChecker::Enter( const parser::OpenMPCancellationPointConstruct &x) { const auto &dir{std::get(x.t)}; - PushContext(dir.source, llvm::omp::Directive::OMPD_cancellation_point); + PushContextAndClauseSets( + dir.source, llvm::omp::Directive::OMPD_cancellation_point); } void OmpStructureChecker::Leave( diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index 1585b0c861add..eff0eb4aa76be 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -25,6 +25,9 @@ using OmpDirectiveSet = Fortran::common::EnumSet; +#define GEN_FLANG_DIRECTIVE_CLAUSE_SETS +#include "llvm/Frontend/OpenMP/OMP.cpp.inc" + namespace llvm { namespace omp { static OmpDirectiveSet parallelSet{Directive::OMPD_distribute_parallel_do, @@ -151,6 +154,9 @@ class OmpStructureChecker : public virtual BaseChecker { void Enter(const parser::OmpScheduleClause &); private: +#define GEN_FLANG_DIRECTIVE_CLAUSE_MAP +#include "llvm/Frontend/OpenMP/OMP.cpp.inc" + struct OmpContext { OmpContext(parser::CharBlock source, llvm::omp::Directive d) : directiveSource{source}, directive{d} {} @@ -216,7 +222,20 @@ class OmpStructureChecker : public virtual BaseChecker { void PushContext(const parser::CharBlock &source, llvm::omp::Directive dir) { ompContext_.emplace_back(source, dir); } - + void SetClauseSets(llvm::omp::Directive dir) { + ompContext_.back().allowedClauses = directiveClausesTable[dir].allowed; + ompContext_.back().allowedOnceClauses = + directiveClausesTable[dir].allowedOnce; + ompContext_.back().allowedExclusiveClauses = + directiveClausesTable[dir].allowedExclusive; + ompContext_.back().requiredClauses = + directiveClausesTable[dir].requiredOneOf; + } + void PushContextAndClauseSets( + const parser::CharBlock &source, llvm::omp::Directive dir) { + PushContext(source, dir); + SetClauseSets(dir); + } void RequiresConstantPositiveParameter( const llvm::omp::Clause &clause, const parser::ScalarIntConstantExpr &i); void RequiresPositiveParameter( diff --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90 index e3f43dc5445e6..77e40e323e5f9 100644 --- a/flang/test/Semantics/omp-clause-validity01.f90 +++ b/flang/test/Semantics/omp-clause-validity01.f90 @@ -458,7 +458,6 @@ enddo !$omp end taskloop simd - !ERROR: REDUCTION clause is not allowed on the TASKLOOP SIMD directive !$omp taskloop simd reduction(+:a) do i = 1, N a = a + 3.14 diff --git a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td index 785a520613b96..3c295a1d7c5f3 100644 --- a/llvm/include/llvm/Frontend/Directive/DirectiveBase.td +++ b/llvm/include/llvm/Frontend/Directive/DirectiveBase.td @@ -43,6 +43,9 @@ class DirectiveLanguage { // Header file included in the implementation code generated. Ususally the // output file of the declaration code generation. Can be left blank. string includeHeader = ""; + + // EnumSet class name used for clauses to generated the allowed clauses map. + string clauseEnumSetClass = ""; } // Information about a specific clause. @@ -92,6 +95,9 @@ class Directive { // List of clauses that are allowed to appear only once. list allowedOnceClauses = []; + // List of clauses that are allowed but mutually exclusive. + list allowedExclusiveClauses = []; + // List of clauses that are required. list requiredClauses = []; diff --git a/llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt b/llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt index 69f503675940d..3ff89888bfd64 100644 --- a/llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt +++ b/llvm/include/llvm/Frontend/OpenMP/CMakeLists.txt @@ -1,3 +1,4 @@ set(LLVM_TARGET_DEFINITIONS OMP.td) tablegen(LLVM OMP.h.inc --gen-directive-decl) +tablegen(LLVM OMP.cpp.inc --gen-directive-gen) add_public_tablegen_target(omp_gen) diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index bd81eeb011272..a565bdf90b3f6 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -24,6 +24,7 @@ def OpenMP : DirectiveLanguage { let makeEnumAvailableInNamespace = 1; let enableBitmaskEnumInNamespace = 1; let includeHeader = "llvm/Frontend/OpenMP/OMP.h.inc"; + let clauseEnumSetClass = "OmpClauseSet"; } //===----------------------------------------------------------------------===// @@ -201,10 +202,7 @@ def OMPC_Notinbranch : Clause<"notinbranch"> {} def OMP_ThreadPrivate : Directive<"threadprivate"> {} def OMP_Parallel : Directive<"parallel"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -212,11 +210,14 @@ def OMP_Parallel : Directive<"parallel"> { VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + ]; } def OMP_Task : Directive<"task"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -224,12 +225,16 @@ def OMP_Task : Directive<"task"> { VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_Simd : Directive<"simd"> { let allowedClauses = [ @@ -237,15 +242,17 @@ def OMP_Simd : Directive<"simd"> { VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + ]; } def OMP_For : Directive<"for"> { let allowedClauses = [ @@ -273,7 +280,8 @@ def OMP_Do : Directive<"do"> { let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause ]; } def OMP_Sections : Directive<"sections"> { @@ -345,30 +353,34 @@ def OMP_Atomic : Directive<"atomic"> { def OMP_Target : Directive<"target"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_Teams : Directive<"teams"> { let allowedClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_Cancel : Directive<"cancel"> { let allowedClauses = [ @@ -386,50 +398,64 @@ def OMP_Requires : Directive<"requires"> { } def OMP_TargetData : Directive<"target data"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause + ]; + let requiredClauses = [ + VersionedClause + ]; } def OMP_TargetEnterData : Directive<"target enter data"> { let allowedClauses = [ + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_TargetExitData : Directive<"target exit data"> { let allowedClauses = [ - VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause, + VersionedClause + ]; + let requiredClauses = [ + VersionedClause ]; } def OMP_TargetParallel : Directive<"target parallel"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_TargetParallelFor : Directive<"target parallel for"> { let allowedClauses = [ @@ -459,27 +485,31 @@ def OMP_TargetParallelFor : Directive<"target parallel for"> { } def OMP_TargetParallelDo : Directive<"target parallel do"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause ]; } def OMP_TargetUpdate : Directive<"target update"> { @@ -558,27 +588,29 @@ def OMP_ParallelForSimd : Directive<"parallel for simd"> { } def OMP_ParallelDoSimd : Directive<"parallel do simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_ParallelMaster : Directive<"parallel master"> { let allowedClauses = [ @@ -597,7 +629,6 @@ def OMP_ParallelMaster : Directive<"parallel master"> { def OMP_ParallelSections : Directive<"parallel sections"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -608,6 +639,9 @@ def OMP_ParallelSections : Directive<"parallel sections"> { VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause + ]; } def OMP_ForSimd : Directive<"for simd"> { let allowedClauses = [ @@ -643,7 +677,8 @@ def OMP_DoSimd : Directive<"do simd"> { VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause ]; } def OMP_CancellationPoint : Directive<"cancellation point"> {} @@ -653,53 +688,74 @@ def OMP_DeclareMapper : Directive<"declare mapper"> { VersionedClause ]; } -def OMP_DeclareSimd : Directive<"declare simd"> {} +def OMP_DeclareSimd : Directive<"declare simd"> { + let allowedClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause + ]; + let allowedExclusiveClauses = [ + VersionedClause, + VersionedClause + ]; +} def OMP_TaskLoop : Directive<"taskloop"> { let allowedClauses = [ - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + ]; + let allowedExclusiveClauses = [ + VersionedClause, + VersionedClause + ]; } def OMP_TaskLoopSimd : Directive<"taskloop simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedExclusiveClauses = [ + VersionedClause, + VersionedClause ]; } def OMP_Distribute : Directive<"distribute"> { @@ -707,10 +763,12 @@ def OMP_Distribute : Directive<"distribute"> { VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause + ]; } def OMP_DeclareTarget : Directive<"declare target"> {} def OMP_EndDeclareTarget : Directive<"end declare target"> {} @@ -735,21 +793,25 @@ def OMP_DistributeParallelFor : Directive<"distribute parallel for"> { } def OMP_DistributeParallelDo : Directive<"distribute parallel do"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_DistributeParallelForSimd : Directive<"distribute parallel for simd"> { @@ -802,22 +864,31 @@ def OMP_DistributeParallelDoSimd : Directive<"distribute parallel do simd"> { } def OMP_DistributeSimd : Directive<"distribute simd"> { let allowedClauses = [ - VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause ]; } + def OMP_TargetParallelForSimd : Directive<"target parallel for simd"> { let allowedClauses = [ VersionedClause, @@ -880,27 +951,33 @@ def OMP_TargetParallelDoSimd : Directive<"target parallel do simd"> { } def OMP_TargetSimd : Directive<"target simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, + VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; } def OMP_TeamsDistribute : Directive<"teams distribute"> { let allowedClauses = [ @@ -919,26 +996,29 @@ def OMP_TeamsDistribute : Directive<"teams distribute"> { } def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } + def OMP_TeamsDistributeParallelForSimd : Directive<"teams distribute parallel for simd"> { let allowedClauses = [ @@ -968,27 +1048,29 @@ def OMP_TeamsDistributeParallelForSimd : def OMP_TeamsDistributeParallelDoSimd : Directive<"teams distribute parallel do simd"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause, ]; } def OMP_TeamsDistributeParallelFor : @@ -1016,68 +1098,78 @@ def OMP_TeamsDistributeParallelFor : def OMP_TeamsDistributeParallelDo : Directive<"teams distribute parallel do"> { let allowedClauses = [ + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; +let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_TargetTeams : Directive<"target teams"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause + VersionedClause, + VersionedClause + ]; + + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause ]; } def OMP_TargetTeamsDistribute : Directive<"target teams distribute"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } + def OMP_TargetTeamsDistributeParallelFor : Directive<"target teams distribute parallel for"> { let allowedClauses = [ @@ -1110,28 +1202,33 @@ def OMP_TargetTeamsDistributeParallelDo : Directive<"target teams distribute parallel do"> { let allowedClauses = [ VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause ]; } def OMP_TargetTeamsDistributeParallelForSimd : @@ -1170,63 +1267,69 @@ def OMP_TargetTeamsDistributeParallelForSimd : def OMP_TargetTeamsDistributeParallelDoSimd : Directive<"target teams distribute parallel do simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, - VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_TargetTeamsDistributeSimd : Directive<"target teams distribute simd"> { let allowedClauses = [ - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, VersionedClause, VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause, - VersionedClause ]; } def OMP_Allocate : Directive<"allocate"> { @@ -1359,7 +1462,22 @@ def OMP_Scan : Directive<"scan"> { } def OMP_BeginDeclareVariant : Directive<"begin declare variant"> {} def OMP_EndDeclareVariant : Directive<"end declare variant"> {} -def OMP_ParallelWorkshare : Directive<"parallel workshare"> {} +def OMP_ParallelWorkshare : Directive<"parallel workshare"> { + let allowedClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause + ]; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause + ]; +} def OMP_Workshare : Directive<"workshare"> {} def OMP_EndDo : Directive<"end do"> {} def OMP_EndDoSimd : Directive<"end do simd"> {} diff --git a/llvm/test/TableGen/directive1.td b/llvm/test/TableGen/directive1.td index 8b3cc8702bd49..b293196d4d556 100644 --- a/llvm/test/TableGen/directive1.td +++ b/llvm/test/TableGen/directive1.td @@ -1,5 +1,6 @@ // RUN: llvm-tblgen -gen-directive-decl -I %p/../../include %s | FileCheck -match-full-lines %s // RUN: llvm-tblgen -gen-directive-impl -I %p/../../include %s | FileCheck -match-full-lines %s -check-prefix=IMPL +// RUN: llvm-tblgen -gen-directive-gen -I %p/../../include %s | FileCheck -match-full-lines %s -check-prefix=GEN include "llvm/Frontend/Directive/DirectiveBase.td" @@ -126,3 +127,57 @@ def TDL_DirA : Directive<"dira"> { // IMPL-NEXT: } // IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind"); // IMPL-NEXT: } +// IMPL-EMPTY: + + + +// GEN: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-EMPTY: +// GEN-NEXT: namespace llvm { +// GEN-NEXT: namespace tdl { +// GEN-EMPTY: +// GEN-NEXT: // Sets for dira +// GEN-EMPTY: +// GEN-NEXT: static allowedClauses_TDLD_dira { +// GEN-NEXT: llvm::tdl::Clause::TDLC_clausea, +// GEN-NEXT: llvm::tdl::Clause::TDLC_clauseb, +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static allowedOnceClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static allowedExclusiveClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static requiredClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-NEXT: } // namespace tdl +// GEN-NEXT: } // namespace llvm +// GEN-EMPTY: +// GEN-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-EMPTY: +// GEN-NEXT: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// GEN-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// GEN-EMPTY: +// GEN-NEXT: struct TdlDirectiveClauses { +// GEN-NEXT: const allowed; +// GEN-NEXT: const allowedOnce; +// GEN-NEXT: const allowedExclusive; +// GEN-NEXT: const requiredOneOf; +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: std::unordered_map +// GEN-NEXT: directiveClausesTable = { +// GEN-NEXT: {llvm::tdl::Directive::TDLD_dira, +// GEN-NEXT: { +// GEN-NEXT: llvm::tdl::allowedClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::allowedOnceClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::allowedExclusiveClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::requiredClauses_TDLD_dira, +// GEN-NEXT: } +// GEN-NEXT: }, +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_MAP + diff --git a/llvm/test/TableGen/directive2.td b/llvm/test/TableGen/directive2.td index 06c7aabcf3adc..517c79d457988 100644 --- a/llvm/test/TableGen/directive2.td +++ b/llvm/test/TableGen/directive2.td @@ -1,5 +1,6 @@ // RUN: llvm-tblgen -gen-directive-decl -I %p/../../include %s | FileCheck -match-full-lines %s // RUN: llvm-tblgen -gen-directive-impl -I %p/../../include %s | FileCheck -match-full-lines %s -check-prefix=IMPL +// RUN: llvm-tblgen -gen-directive-gen -I %p/../../include %s | FileCheck -match-full-lines %s -check-prefix=GEN include "llvm/Frontend/Directive/DirectiveBase.td" @@ -71,7 +72,7 @@ def TDL_DirA : Directive<"dira"> { // IMPL-NEXT: using namespace llvm; // IMPL-NEXT: using namespace tdl; // IMPL-EMPTY: -// IMPL: Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) { +// IMPL-NEXT: Directive llvm::tdl::getTdlDirectiveKind(llvm::StringRef Str) { // IMPL-NEXT: return llvm::StringSwitch(Str) // IMPL-NEXT: .Case("dira",TDLD_dira) // IMPL-NEXT: .Default(TDLD_dira); @@ -119,3 +120,54 @@ def TDL_DirA : Directive<"dira"> { // IMPL-NEXT: } // IMPL-NEXT: llvm_unreachable("Invalid Tdl Directive kind"); // IMPL-NEXT: } + + +// GEN: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-EMPTY: +// GEN-NEXT: namespace llvm { +// GEN-NEXT: namespace tdl { +// GEN-EMPTY: +// GEN-NEXT: // Sets for dira +// GEN-EMPTY: +// GEN-NEXT: static allowedClauses_TDLD_dira { +// GEN-NEXT: llvm::tdl::Clause::TDLC_clausea, +// GEN-NEXT: llvm::tdl::Clause::TDLC_clauseb, +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static allowedOnceClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static allowedExclusiveClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: static requiredClauses_TDLD_dira { +// GEN-NEXT: }; +// GEN-NEXT: } // namespace tdl +// GEN-NEXT: } // namespace llvm +// GEN-EMPTY: +// GEN-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_SETS +// GEN-EMPTY: +// GEN-NEXT: #ifdef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// GEN-NEXT: #undef GEN_FLANG_DIRECTIVE_CLAUSE_MAP +// GEN-EMPTY: +// GEN-NEXT: struct TdlDirectiveClauses { +// GEN-NEXT: const allowed; +// GEN-NEXT: const allowedOnce; +// GEN-NEXT: const allowedExclusive; +// GEN-NEXT: const requiredOneOf; +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: std::unordered_map +// GEN-NEXT: directiveClausesTable = { +// GEN-NEXT: {llvm::tdl::Directive::TDLD_dira, +// GEN-NEXT: { +// GEN-NEXT: llvm::tdl::allowedClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::allowedOnceClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::allowedExclusiveClauses_TDLD_dira, +// GEN-NEXT: llvm::tdl::requiredClauses_TDLD_dira, +// GEN-NEXT: } +// GEN-NEXT: }, +// GEN-NEXT: }; +// GEN-EMPTY: +// GEN-NEXT: #endif // GEN_FLANG_DIRECTIVE_CLAUSE_MAP diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp index f51f98872bb51..fc4a6757f8086 100644 --- a/llvm/utils/TableGen/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/DirectiveEmitter.cpp @@ -14,12 +14,30 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringSet.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" using namespace llvm; +namespace { +// Simple RAII helper for defining ifdef-undef-endif scopes. +class IfDefScope { +public: + IfDefScope(StringRef Name, raw_ostream &OS) : Name(Name), OS(OS) { + OS << "#ifdef " << Name << "\n" + << "#undef " << Name << "\n"; + } + + ~IfDefScope() { OS << "\n#endif // " << Name << "\n\n"; } + +private: + StringRef Name; + raw_ostream &OS; +}; +} // end anonymous namespace + namespace llvm { // Get Directive or Clause name formatted by replacing whitespaces with @@ -205,16 +223,21 @@ void GenerateGetKind(const std::vector &Records, raw_ostream &OS, void GenerateCaseForVersionedClauses(const std::vector &Clauses, raw_ostream &OS, StringRef DirectiveName, StringRef DirectivePrefix, - StringRef ClausePrefix) { + StringRef ClausePrefix, + llvm::StringSet<> &Cases) { for (const auto &C : Clauses) { const auto MinVersion = C->getValueAsInt("minVersion"); const auto MaxVersion = C->getValueAsInt("maxVersion"); const auto SpecificClause = C->getValueAsDef("clause"); - const auto ClauseName = SpecificClause->getValueAsString("name"); - OS << " case " << ClausePrefix << getFormattedName(ClauseName) - << ":\n"; - OS << " return " << MinVersion << " <= Version && " << MaxVersion - << " >= Version;\n"; + const auto ClauseName = + getFormattedName(SpecificClause->getValueAsString("name")); + + if (Cases.find(ClauseName) == Cases.end()) { + Cases.insert(ClauseName); + OS << " case " << ClausePrefix << ClauseName << ":\n"; + OS << " return " << MinVersion << " <= Version && " << MaxVersion + << " >= Version;\n"; + } } } @@ -239,24 +262,32 @@ void GenerateIsAllowedClause(const std::vector &Directives, const auto &AllowedClauses = D->getValueAsListOfDefs("allowedClauses"); const auto &AllowedOnceClauses = D->getValueAsListOfDefs("allowedOnceClauses"); + const auto &AllowedExclusiveClauses = + D->getValueAsListOfDefs("allowedExclusiveClauses"); const auto &RequiredClauses = D->getValueAsListOfDefs("requiredClauses"); OS << " case " << DirectivePrefix << getFormattedName(DirectiveName) << ":\n"; - if (AllowedClauses.size() == 0 && AllowedOnceClauses.size() == 0 && - AllowedOnceClauses.size() == 0) { + if (AllowedClauses.size() == 0 && AllowedOnceClauses.size() == 0 && + AllowedExclusiveClauses.size() == 0 && RequiredClauses.size() == 0) { OS << " return false;\n"; } else { OS << " switch (C) {\n"; + llvm::StringSet<> Cases; + GenerateCaseForVersionedClauses(AllowedClauses, OS, DirectiveName, - DirectivePrefix, ClausePrefix); + DirectivePrefix, ClausePrefix, Cases); GenerateCaseForVersionedClauses(AllowedOnceClauses, OS, DirectiveName, - DirectivePrefix, ClausePrefix); + DirectivePrefix, ClausePrefix, Cases); + + GenerateCaseForVersionedClauses(AllowedExclusiveClauses, OS, + DirectiveName, DirectivePrefix, + ClausePrefix, Cases); GenerateCaseForVersionedClauses(RequiredClauses, OS, DirectiveName, - DirectivePrefix, ClausePrefix); + DirectivePrefix, ClausePrefix, Cases); OS << " default:\n"; OS << " return false;\n"; @@ -271,9 +302,143 @@ void GenerateIsAllowedClause(const std::vector &Directives, OS << "}\n"; // End of function isAllowedClauseForDirective } +// Generate a simple enum set with the give clauses. +void GenerateClauseSet(const std::vector &Clauses, raw_ostream &OS, + StringRef ClauseEnumSetClass, StringRef ClauseSetPrefix, + StringRef DirectiveName, StringRef DirectivePrefix, + StringRef ClausePrefix, StringRef CppNamespace) { + + OS << "\n"; + OS << " static " << ClauseEnumSetClass << " " << ClauseSetPrefix + << DirectivePrefix << getFormattedName(DirectiveName) << " {\n"; + + for (const auto &C : Clauses) { + const auto SpecificClause = C->getValueAsDef("clause"); + const auto ClauseName = SpecificClause->getValueAsString("name"); + OS << " llvm::" << CppNamespace << "::Clause::" << ClausePrefix + << getFormattedName(ClauseName) << ",\n"; + } + OS << " };\n"; +} + +// Generate an enum set for the 4 kinds of clauses linked to a directive. +void GenerateDirectiveClauseSets(const std::vector &Directives, + raw_ostream &OS, StringRef LanguageName, + StringRef ClauseEnumSetClass, + StringRef DirectivePrefix, + StringRef ClausePrefix, + StringRef CppNamespace) { + + IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_SETS", OS); + + OS << "\n"; + OS << "namespace llvm {\n"; + + // Open namespaces defined in the directive language. + llvm::SmallVector Namespaces; + llvm::SplitString(CppNamespace, Namespaces, "::"); + for (auto Ns : Namespaces) + OS << "namespace " << Ns << " {\n"; + + for (const auto &D : Directives) { + const auto DirectiveName = D->getValueAsString("name"); + + const auto &AllowedClauses = D->getValueAsListOfDefs("allowedClauses"); + const auto &AllowedOnceClauses = + D->getValueAsListOfDefs("allowedOnceClauses"); + const auto &AllowedExclusiveClauses = + D->getValueAsListOfDefs("allowedExclusiveClauses"); + const auto &RequiredClauses = D->getValueAsListOfDefs("requiredClauses"); + + OS << "\n"; + OS << " // Sets for " << DirectiveName << "\n"; + + GenerateClauseSet(AllowedClauses, OS, ClauseEnumSetClass, "allowedClauses_", + DirectiveName, DirectivePrefix, ClausePrefix, + CppNamespace); + GenerateClauseSet(AllowedOnceClauses, OS, ClauseEnumSetClass, + "allowedOnceClauses_", DirectiveName, DirectivePrefix, + ClausePrefix, CppNamespace); + GenerateClauseSet(AllowedExclusiveClauses, OS, ClauseEnumSetClass, + "allowedExclusiveClauses_", DirectiveName, + DirectivePrefix, ClausePrefix, CppNamespace); + GenerateClauseSet(RequiredClauses, OS, ClauseEnumSetClass, + "requiredClauses_", DirectiveName, DirectivePrefix, + ClausePrefix, CppNamespace); + } + + // Closing namespaces + for (auto Ns : llvm::reverse(Namespaces)) + OS << "} // namespace " << Ns << "\n"; + + OS << "} // namespace llvm\n"; +} + +// Generate a map of directive (key) with DirectiveClauses struct as values. +// The struct holds the 4 sets of enumeration for the 4 kinds of clauses +// allowances (allowed, allowed once, allowed exclusive and required). +void GenerateDirectiveClauseMap(const std::vector &Directives, + raw_ostream &OS, StringRef LanguageName, + StringRef ClauseEnumSetClass, + StringRef DirectivePrefix, + StringRef ClausePrefix, + StringRef CppNamespace) { + + IfDefScope Scope("GEN_FLANG_DIRECTIVE_CLAUSE_MAP", OS); + + OS << "\n"; + OS << "struct " << LanguageName << "DirectiveClauses {\n"; + OS << " const " << ClauseEnumSetClass << " allowed;\n"; + OS << " const " << ClauseEnumSetClass << " allowedOnce;\n"; + OS << " const " << ClauseEnumSetClass << " allowedExclusive;\n"; + OS << " const " << ClauseEnumSetClass << " requiredOneOf;\n"; + OS << "};\n"; + + OS << "\n"; + + OS << "std::unordered_map\n"; + OS << " directiveClausesTable = {\n"; + + for (const auto &D : Directives) { + const auto FormattedDirectiveName = + getFormattedName(D->getValueAsString("name")); + OS << " {llvm::" << CppNamespace << "::Directive::" << DirectivePrefix + << FormattedDirectiveName << ",\n"; + OS << " {\n"; + OS << " llvm::" << CppNamespace << "::allowedClauses_" + << DirectivePrefix << FormattedDirectiveName << ",\n"; + OS << " llvm::" << CppNamespace << "::allowedOnceClauses_" + << DirectivePrefix << FormattedDirectiveName << ",\n"; + OS << " llvm::" << CppNamespace << "::allowedExclusiveClauses_" + << DirectivePrefix << FormattedDirectiveName << ",\n"; + OS << " llvm::" << CppNamespace << "::requiredClauses_" + << DirectivePrefix << FormattedDirectiveName << ",\n"; + OS << " }\n"; + OS << " },\n"; + } + + OS << "};\n"; +} + // Generate the implemenation section for the enumeration in the directive // language -void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { +void EmitDirectivesFlangImpl(const std::vector &Directives, + raw_ostream &OS, StringRef LanguageName, + StringRef ClauseEnumSetClass, + StringRef DirectivePrefix, StringRef ClausePrefix, + StringRef CppNamespace) { + + GenerateDirectiveClauseSets(Directives, OS, LanguageName, ClauseEnumSetClass, + DirectivePrefix, ClausePrefix, CppNamespace); + + GenerateDirectiveClauseMap(Directives, OS, LanguageName, ClauseEnumSetClass, + DirectivePrefix, ClausePrefix, CppNamespace); +} + +// Generate the implemenation section for the enumeration in the directive +// language. +void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) { const auto &DirectiveLanguages = Records.getAllDerivedDefinitions("DirectiveLanguage"); @@ -289,12 +454,40 @@ void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { StringRef LanguageName = DirectiveLanguage->getValueAsString("name"); StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix"); StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace"); - StringRef IncludeHeader = - DirectiveLanguage->getValueAsString("includeHeader"); + StringRef ClauseEnumSetClass = + DirectiveLanguage->getValueAsString("clauseEnumSetClass"); const auto &Directives = Records.getAllDerivedDefinitions("Directive"); const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); + EmitDirectivesFlangImpl(Directives, OS, LanguageName, ClauseEnumSetClass, + DirectivePrefix, ClausePrefix, CppNamespace); +} + +// Generate the implemenation for the enumeration in the directive +// language. This code can be included in library. +void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { + + const auto &DirectiveLanguages = + Records.getAllDerivedDefinitions("DirectiveLanguage"); + + if (DirectiveLanguages.size() != 1) { + PrintError("A single definition of DirectiveLanguage is needed."); + return; + } + + const auto &DirectiveLanguage = DirectiveLanguages[0]; + StringRef DirectivePrefix = + DirectiveLanguage->getValueAsString("directivePrefix"); + StringRef LanguageName = DirectiveLanguage->getValueAsString("name"); + StringRef ClausePrefix = DirectiveLanguage->getValueAsString("clausePrefix"); + StringRef CppNamespace = DirectiveLanguage->getValueAsString("cppNamespace"); + const auto &Directives = Records.getAllDerivedDefinitions("Directive"); + const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); + + StringRef IncludeHeader = + DirectiveLanguage->getValueAsString("includeHeader"); + if (!IncludeHeader.empty()) OS << "#include \"" << IncludeHeader << "\"\n\n"; @@ -323,6 +516,7 @@ void EmitDirectivesImpl(RecordKeeper &Records, raw_ostream &OS) { GenerateGetName(Clauses, OS, "Clause", ClausePrefix, LanguageName, CppNamespace); + // isAllowedClauseForDirective(Directive D, Clause C, unsigned Version) GenerateIsAllowedClause(Directives, OS, LanguageName, DirectivePrefix, ClausePrefix, CppNamespace); } diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp index 7438749a1243e..8015a58471cad 100644 --- a/llvm/utils/TableGen/TableGen.cpp +++ b/llvm/utils/TableGen/TableGen.cpp @@ -56,6 +56,7 @@ enum ActionType { GenAutomata, GenDirectivesEnumDecl, GenDirectivesEnumImpl, + GenDirectivesEnumGen, }; namespace llvm { @@ -132,9 +133,11 @@ cl::opt Action( "Generate llvm-exegesis tables"), clEnumValN(GenAutomata, "gen-automata", "Generate generic automata"), clEnumValN(GenDirectivesEnumDecl, "gen-directive-decl", - "Generate directive related declaration code"), + "Generate directive related declaration code (header file)"), clEnumValN(GenDirectivesEnumImpl, "gen-directive-impl", - "Generate directive related implementation code"))); + "Generate directive related implementation code"), + clEnumValN(GenDirectivesEnumGen, "gen-directive-gen", + "Generate directive related implementation code part"))); cl::OptionCategory PrintEnumsCat("Options for -print-enums"); cl::opt Class("class", cl::desc("Print Enum list for this class"), @@ -265,6 +268,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenDirectivesEnumImpl: EmitDirectivesImpl(Records, OS); break; + case GenDirectivesEnumGen: + EmitDirectivesGen(Records, OS); + break; } return false; diff --git a/llvm/utils/TableGen/TableGenBackends.h b/llvm/utils/TableGen/TableGenBackends.h index 9e6171abcabfc..92204f39f8fa0 100644 --- a/llvm/utils/TableGen/TableGenBackends.h +++ b/llvm/utils/TableGen/TableGenBackends.h @@ -92,6 +92,7 @@ void EmitExegesis(RecordKeeper &RK, raw_ostream &OS); void EmitAutomata(RecordKeeper &RK, raw_ostream &OS); void EmitDirectivesDecl(RecordKeeper &RK, raw_ostream &OS); void EmitDirectivesImpl(RecordKeeper &RK, raw_ostream &OS); +void EmitDirectivesGen(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace From 5d2c3e031a6861b3e95673d0e238c09938dd9c0d Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" Date: Sat, 11 Jul 2020 10:04:27 -0400 Subject: [PATCH 025/771] Fix regression due to test hip-version.hip Added RocmInstallationDetector to Darwin and MinGW. Fixed duplicate ROCm detector in ROCm toolchain. --- clang/lib/Driver/ToolChains/AMDGPU.cpp | 6 +++--- clang/lib/Driver/ToolChains/AMDGPU.h | 3 --- clang/lib/Driver/ToolChains/Darwin.cpp | 8 +++++++- clang/lib/Driver/ToolChains/Darwin.h | 4 ++++ clang/lib/Driver/ToolChains/FreeBSD.cpp | 5 +++++ clang/lib/Driver/ToolChains/FreeBSD.h | 2 ++ clang/lib/Driver/ToolChains/HIP.cpp | 1 - clang/lib/Driver/ToolChains/MinGW.cpp | 9 ++++++++- clang/lib/Driver/ToolChains/MinGW.h | 4 ++++ clang/test/Driver/hip-version.hip | 12 ++++++++++++ 10 files changed, 45 insertions(+), 9 deletions(-) diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index cfc71d7810b46..bc6d1fcd4a008 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -489,9 +489,9 @@ bool AMDGPUToolChain::isWave64(const llvm::opt::ArgList &DriverArgs, /// ROCM Toolchain ROCMToolChain::ROCMToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : AMDGPUToolChain(D, Triple, Args), - RocmInstallation(D, Triple, Args, /*DetectHIPRuntime=*/false, - /*DetectDeviceLib=*/true) {} + : AMDGPUToolChain(D, Triple, Args) { + RocmInstallation.detectDeviceLibrary(); +} void AMDGPUToolChain::addClangTargetOptions( const llvm::opt::ArgList &DriverArgs, diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h index 71c66188b0456..5d44faf28b053 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.h +++ b/clang/lib/Driver/ToolChains/AMDGPU.h @@ -90,9 +90,6 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF { }; class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain { -protected: - RocmInstallationDetector RocmInstallation; - public: ROCMToolChain(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 6bf42e6029eb5..2e1190c34ea7a 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -779,7 +779,7 @@ MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) /// Darwin - Darwin tool chain for i386 and x86_64. Darwin::Darwin(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : MachO(D, Triple, Args), TargetInitialized(false), - CudaInstallation(D, Triple, Args) {} + CudaInstallation(D, Triple, Args), RocmInstallation(D, Triple, Args) {} types::ID MachO::LookupTypeForExtension(StringRef Ext) const { types::ID Ty = ToolChain::LookupTypeForExtension(Ext); @@ -831,6 +831,11 @@ void Darwin::AddCudaIncludeArgs(const ArgList &DriverArgs, CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); } +void Darwin::AddHIPIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); +} + // This is just a MachO name translation routine and there's no // way to join this into ARMTargetParser without breaking all // other assumptions. Maybe MachO should consider standardising @@ -2736,4 +2741,5 @@ SanitizerMask Darwin::getSupportedSanitizers() const { void Darwin::printVerboseInfo(raw_ostream &OS) const { CudaInstallation.print(OS); + RocmInstallation.print(OS); } diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index a543a8fc27b9d..64c252efea7df 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H #include "Cuda.h" +#include "ROCm.h" #include "clang/Driver/DarwinSDKInfo.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -293,6 +294,7 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { mutable Optional SDKInfo; CudaInstallationDetector CudaInstallation; + RocmInstallationDetector RocmInstallation; private: void AddDeploymentTarget(llvm::opt::DerivedArgList &Args) const; @@ -475,6 +477,8 @@ class LLVM_LIBRARY_VISIBILITY Darwin : public MachO { void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; bool UseObjCMixedDispatch() const override { // This is only used with the non-fragile ABI and non-legacy dispatch. diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp index 14cf278c19d9e..909ac5e992129 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -425,6 +425,11 @@ void FreeBSD::AddCudaIncludeArgs(const ArgList &DriverArgs, CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); } +void FreeBSD::AddHIPIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); +} + Tool *FreeBSD::buildAssembler() const { return new tools::freebsd::Assembler(*this); } diff --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h index bca3f6b741b6a..abc0876cef260 100644 --- a/clang/lib/Driver/ToolChains/FreeBSD.h +++ b/clang/lib/Driver/ToolChains/FreeBSD.h @@ -68,6 +68,8 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF { llvm::opt::ArgStringList &CmdArgs) const override; void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; llvm::ExceptionHandling GetExceptionModel(const llvm::opt::ArgList &Args) const override; diff --git a/clang/lib/Driver/ToolChains/HIP.cpp b/clang/lib/Driver/ToolChains/HIP.cpp index 32734f5c11809..7d17f809690ea 100644 --- a/clang/lib/Driver/ToolChains/HIP.cpp +++ b/clang/lib/Driver/ToolChains/HIP.cpp @@ -224,7 +224,6 @@ HIPToolChain::HIPToolChain(const Driver &D, const llvm::Triple &Triple, // Lookup binaries into the driver directory, this is used to // discover the clang-offload-bundler executable. getProgramPaths().push_back(getDriver().Dir); - RocmInstallation.detectHIPRuntime(); } void HIPToolChain::addClangTargetOptions( diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index b233e210d889e..a1a1b413fb6c6 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -398,7 +398,8 @@ llvm::ErrorOr toolchains::MinGW::findClangRelativeSysroot() { toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) - : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) { + : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), + RocmInstallation(D, Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().SysRoot.size()) @@ -500,8 +501,14 @@ void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); } +void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); +} + void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { CudaInstallation.print(OS); + RocmInstallation.print(OS); } // Include directories for various hosts: diff --git a/clang/lib/Driver/ToolChains/MinGW.h b/clang/lib/Driver/ToolChains/MinGW.h index 46264a55cfc7b..2f1559fcf34cd 100644 --- a/clang/lib/Driver/ToolChains/MinGW.h +++ b/clang/lib/Driver/ToolChains/MinGW.h @@ -11,6 +11,7 @@ #include "Cuda.h" #include "Gnu.h" +#include "ROCm.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/Support/ErrorOr.h" @@ -81,6 +82,8 @@ class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain { void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; void printVerboseInfo(raw_ostream &OS) const override; @@ -91,6 +94,7 @@ class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain { private: CudaInstallationDetector CudaInstallation; + RocmInstallationDetector RocmInstallation; std::string Base; std::string GccLibDir; diff --git a/clang/test/Driver/hip-version.hip b/clang/test/Driver/hip-version.hip index cf80ae15ac6da..eb1295210cfc1 100644 --- a/clang/test/Driver/hip-version.hip +++ b/clang/test/Driver/hip-version.hip @@ -5,6 +5,10 @@ // RUN: %clang -v --rocm-path=%S/Inputs/rocm 2>&1 \ // RUN: | FileCheck -check-prefixes=FOUND %s +// RUN: %clang -v --rocm-path=%S/Inputs/rocm 2>&1 \ +// RUN: -target amdgcn-amd-amdhsa \ +// RUN: | FileCheck -check-prefixes=FOUND %s + // FOUND: Found HIP installation: {{.*Inputs.*rocm}}, version 3.6.20214-a2917cd // When --rocm-path is set and .hipVersion is not found, use default version @@ -12,11 +16,19 @@ // RUN: %clang -v --rocm-path=%S 2>&1 \ // RUN: | FileCheck -check-prefixes=DEFAULT %s +// RUN: %clang -v --rocm-path=%S 2>&1 \ +// RUN: -target amdgcn-amd-amdhsa \ +// RUN: | FileCheck -check-prefixes=DEFAULT %s + // DEFAULT: Found HIP installation: {{.*Driver}}, version 3.5. // RUN: %clang -v --rocm-path=%S --hip-version=3.7.0 2>&1 \ // RUN: | FileCheck -check-prefixes=SPECIFIED %s +// RUN: %clang -v --rocm-path=%S --hip-version=3.7.0 2>&1 \ +// RUN: -target amdgcn-amd-amdhsa \ +// RUN: | FileCheck -check-prefixes=SPECIFIED %s + // SPECIFIED: Found HIP installation: {{.*Driver}}, version 3.7.0 // RUN: %clang -v --rocm-path=%S --hip-version=3.7 2>&1 \ From 5937434677afc5be47977f8d340ff499589f2ef3 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Sat, 11 Jul 2020 11:57:17 -0500 Subject: [PATCH 026/771] [OpenMP] Silence unused symbol warning with proper ifdefs --- openmp/libomptarget/deviceRTLs/common/src/reduction.cu | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openmp/libomptarget/deviceRTLs/common/src/reduction.cu b/openmp/libomptarget/deviceRTLs/common/src/reduction.cu index 0230fa26ac107..7604f024eeb4d 100644 --- a/openmp/libomptarget/deviceRTLs/common/src/reduction.cu +++ b/openmp/libomptarget/deviceRTLs/common/src/reduction.cu @@ -54,6 +54,7 @@ INLINE static void gpu_irregular_warp_reduce(void *reduce_data, } } +#if !defined(__CUDA_ARCH__) || __CUDA_ARCH__ < 700 INLINE static uint32_t gpu_irregular_simd_reduce(void *reduce_data, kmp_ShuffleReductFctPtr shflFct) { uint32_t size, remote_id, physical_lane_id; @@ -72,6 +73,7 @@ gpu_irregular_simd_reduce(void *reduce_data, kmp_ShuffleReductFctPtr shflFct) { } while (logical_lane_id % 2 == 0 && size > 1); return (logical_lane_id == 0); } +#endif INLINE static int32_t nvptx_parallel_reduce_nowait( From 8f183d9f3d13d66a679bd449b1f5d34942560028 Mon Sep 17 00:00:00 2001 From: clementval Date: Sat, 11 Jul 2020 12:59:14 -0400 Subject: [PATCH 027/771] [openmp] Remove unused variable in DirectiveEmitter --- llvm/utils/TableGen/DirectiveEmitter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/utils/TableGen/DirectiveEmitter.cpp b/llvm/utils/TableGen/DirectiveEmitter.cpp index fc4a6757f8086..ebcd6873205ea 100644 --- a/llvm/utils/TableGen/DirectiveEmitter.cpp +++ b/llvm/utils/TableGen/DirectiveEmitter.cpp @@ -458,7 +458,6 @@ void EmitDirectivesGen(RecordKeeper &Records, raw_ostream &OS) { DirectiveLanguage->getValueAsString("clauseEnumSetClass"); const auto &Directives = Records.getAllDerivedDefinitions("Directive"); - const auto &Clauses = Records.getAllDerivedDefinitions("Clause"); EmitDirectivesFlangImpl(Directives, OS, LanguageName, ClauseEnumSetClass, DirectivePrefix, ClausePrefix, CppNamespace); From d8c35031a39e7b1bf9524ddd325c7a91dbb05f1d Mon Sep 17 00:00:00 2001 From: Stephen Neuendorffer Date: Sat, 11 Jul 2020 11:47:07 -0700 Subject: [PATCH 028/771] [examples] fix ExceptionDemo Code didn't compile in a release build. Guard debug output with ifndef NDEBUG. Differential Revision: https://reviews.llvm.org/D83628 --- llvm/examples/ExceptionDemo/ExceptionDemo.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp index 0ecb527f4ec05..1b3ec7c91ddee 100644 --- a/llvm/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/llvm/examples/ExceptionDemo/ExceptionDemo.cpp @@ -792,7 +792,7 @@ _Unwind_Reason_Code ourPersonality(int version, _Unwind_Action actions, } #endif - const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context); + const uint8_t *lsda = (const uint8_t *)_Unwind_GetLanguageSpecificData(context); #ifdef DEBUG fprintf(stderr, @@ -1959,11 +1959,13 @@ int main(int argc, char *argv[]) { executionEngine->finalizeObject(); +#ifndef NDEBUG fprintf(stderr, "\nBegin module dump:\n\n"); module->dump(); fprintf(stderr, "\nEnd module dump:\n"); +#endif fprintf(stderr, "\n\nBegin Test:\n"); From 47872adf6ae236c798d05b7229e00f363ab2fe0f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sat, 11 Jul 2020 12:21:41 -0700 Subject: [PATCH 029/771] [X86] Add test cases for missed opportunities to use vpternlog due to a bitcast between the logic ops. These test cases fail to use vpternlog because the AND was converted to a blend shuffle and then converted back to AND during shuffle lowering. This results in the AND having a different type than it started with. This prevents our custom matching logic from seeing the two logic ops. --- llvm/test/CodeGen/X86/avx512-logic.ll | 34 +++++++++++++++++++ llvm/test/CodeGen/X86/avx512vl-logic.ll | 44 +++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/llvm/test/CodeGen/X86/avx512-logic.ll b/llvm/test/CodeGen/X86/avx512-logic.ll index c2a4da1ba5622..88a3b5aea9bd4 100644 --- a/llvm/test/CodeGen/X86/avx512-logic.ll +++ b/llvm/test/CodeGen/X86/avx512-logic.ll @@ -885,3 +885,37 @@ define <16 x i32> @ternlog_xor_andn(<16 x i32> %x, <16 x i32> %y, <16 x i32> %z) %c = xor <16 x i32> %b, %z ret <16 x i32> %c } + +define <16 x i32> @ternlog_or_and_mask(<16 x i32> %x, <16 x i32> %y) { +; KNL-LABEL: ternlog_or_and_mask: +; KNL: ## %bb.0: +; KNL-NEXT: vpandq {{.*}}(%rip), %zmm0, %zmm0 +; KNL-NEXT: vpord %zmm1, %zmm0, %zmm0 +; KNL-NEXT: retq +; +; SKX-LABEL: ternlog_or_and_mask: +; SKX: ## %bb.0: +; SKX-NEXT: vandps {{.*}}(%rip), %zmm0, %zmm0 +; SKX-NEXT: vorps %zmm1, %zmm0, %zmm0 +; SKX-NEXT: retq + %a = and <16 x i32> %x, + %b = or <16 x i32> %a, %y + ret <16 x i32> %b +} + +define <8 x i64> @ternlog_xor_and_mask(<8 x i64> %x, <8 x i64> %y) { +; KNL-LABEL: ternlog_xor_and_mask: +; KNL: ## %bb.0: +; KNL-NEXT: vpandd {{.*}}(%rip), %zmm0, %zmm0 +; KNL-NEXT: vpxorq %zmm1, %zmm0, %zmm0 +; KNL-NEXT: retq +; +; SKX-LABEL: ternlog_xor_and_mask: +; SKX: ## %bb.0: +; SKX-NEXT: vandps {{.*}}(%rip), %zmm0, %zmm0 +; SKX-NEXT: vxorps %zmm1, %zmm0, %zmm0 +; SKX-NEXT: retq + %a = and <8 x i64> %x, + %b = xor <8 x i64> %a, %y + ret <8 x i64> %b +} diff --git a/llvm/test/CodeGen/X86/avx512vl-logic.ll b/llvm/test/CodeGen/X86/avx512vl-logic.ll index 0647f4e33bf23..26d905ebeae77 100644 --- a/llvm/test/CodeGen/X86/avx512vl-logic.ll +++ b/llvm/test/CodeGen/X86/avx512vl-logic.ll @@ -987,3 +987,47 @@ define <4 x i32> @ternlog_xor_andn(<4 x i32> %x, <4 x i32> %y, <4 x i32> %z) { %c = xor <4 x i32> %b, %z ret <4 x i32> %c } + +define <4 x i32> @ternlog_or_and_mask(<4 x i32> %x, <4 x i32> %y) { +; CHECK-LABEL: ternlog_or_and_mask: +; CHECK: ## %bb.0: +; CHECK-NEXT: vandps {{.*}}(%rip), %xmm0, %xmm0 +; CHECK-NEXT: vorps %xmm1, %xmm0, %xmm0 +; CHECK-NEXT: retq + %a = and <4 x i32> %x, + %b = or <4 x i32> %a, %y + ret <4 x i32> %b +} + +define <8 x i32> @ternlog_or_and_mask_ymm(<8 x i32> %x, <8 x i32> %y) { +; CHECK-LABEL: ternlog_or_and_mask_ymm: +; CHECK: ## %bb.0: +; CHECK-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +; CHECK-NEXT: vorps %ymm1, %ymm0, %ymm0 +; CHECK-NEXT: retq + %a = and <8 x i32> %x, + %b = or <8 x i32> %a, %y + ret <8 x i32> %b +} + +define <2 x i64> @ternlog_xor_and_mask(<2 x i64> %x, <2 x i64> %y) { +; CHECK-LABEL: ternlog_xor_and_mask: +; CHECK: ## %bb.0: +; CHECK-NEXT: vandps {{.*}}(%rip), %xmm0, %xmm0 +; CHECK-NEXT: vxorps %xmm1, %xmm0, %xmm0 +; CHECK-NEXT: retq + %a = and <2 x i64> %x, + %b = xor <2 x i64> %a, %y + ret <2 x i64> %b +} + +define <4 x i64> @ternlog_xor_and_mask_ymm(<4 x i64> %x, <4 x i64> %y) { +; CHECK-LABEL: ternlog_xor_and_mask_ymm: +; CHECK: ## %bb.0: +; CHECK-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +; CHECK-NEXT: vxorps %ymm1, %ymm0, %ymm0 +; CHECK-NEXT: retq + %a = and <4 x i64> %x, + %b = xor <4 x i64> %a, %y + ret <4 x i64> %b +} From 3b04af4d84fbffa6a2e90cfd187ed01092b45684 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sat, 11 Jul 2020 20:05:28 +0000 Subject: [PATCH 030/771] Fix some memory leak in MLIRContext with respect to registered types/attributes interfaces Differential Revision: https://reviews.llvm.org/D83618 --- mlir/lib/IR/MLIRContext.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp index 4c31ef318fd9b..a4e833cbf77c5 100644 --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -331,6 +331,12 @@ class MLIRContextImpl { public: MLIRContextImpl() : identifiers(identifierAllocator) {} + ~MLIRContextImpl() { + for (auto typeMapping : registeredTypes) + typeMapping.second->~AbstractType(); + for (auto attrMapping : registeredAttributes) + attrMapping.second->~AbstractAttribute(); + } }; } // end namespace mlir From 44b0b7cf6605c41728f445c363415b9b6f48db04 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sat, 11 Jul 2020 20:05:37 +0000 Subject: [PATCH 031/771] Fix one memory leak in the MLIRParser by using std::unique_ptr to hold the new block pointer This is NFC when there is no parsing error. Differential Revision: https://reviews.llvm.org/D83619 --- mlir/lib/Parser/Parser.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/mlir/lib/Parser/Parser.cpp b/mlir/lib/Parser/Parser.cpp index 0e4589a209181..fc9d449ecc143 100644 --- a/mlir/lib/Parser/Parser.cpp +++ b/mlir/lib/Parser/Parser.cpp @@ -1504,7 +1504,8 @@ ParseResult OperationParser::parseRegion( pushSSANameScope(isIsolatedNameScope); // Parse the first block directly to allow for it to be unnamed. - Block *block = new Block(); + auto owning_block = std::make_unique(); + Block *block = owning_block.get(); // Add arguments to the entry block. if (!entryArguments.empty()) { @@ -1519,7 +1520,6 @@ ParseResult OperationParser::parseRegion( } if (addDefinition(placeholderArgPair.first, block->addArgument(placeholderArgPair.second))) { - delete block; return failure(); } } @@ -1530,19 +1530,17 @@ ParseResult OperationParser::parseRegion( } if (parseBlock(block)) { - delete block; return failure(); } // Verify that no other arguments were parsed. if (!entryArguments.empty() && block->getNumArguments() > entryArguments.size()) { - delete block; return emitError("entry block arguments were already defined"); } // Parse the rest of the region. - region.push_back(block); + region.push_back(owning_block.release()); if (parseRegionBody(region)) return failure(); From b8409c03ed90807f3d49c7d98dceea98cf461f7a Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Sat, 11 Jul 2020 16:19:09 -0400 Subject: [PATCH 032/771] Fix `-Wreturn-type` warning. NFC. --- clang/lib/Tooling/Syntax/BuildTree.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Tooling/Syntax/BuildTree.cpp b/clang/lib/Tooling/Syntax/BuildTree.cpp index 6d13f1ace83ba..1f192180ec451 100644 --- a/clang/lib/Tooling/Syntax/BuildTree.cpp +++ b/clang/lib/Tooling/Syntax/BuildTree.cpp @@ -750,6 +750,7 @@ class BuildTreeVisitor : public RecursiveASTVisitor { return new (allocator()) syntax::FloatUserDefinedLiteralExpression; } } + llvm_unreachable("Unknown literal operator kind."); } bool WalkUpFromUserDefinedLiteral(UserDefinedLiteral *S) { From 6792069a3fdb412d06dd3cc42a6181c6fb7db860 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 11 Jul 2020 22:51:25 +0200 Subject: [PATCH 033/771] [NewGVN] Regenerate test checks (NFC) --- llvm/test/Transforms/NewGVN/assumes.ll | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/llvm/test/Transforms/NewGVN/assumes.ll b/llvm/test/Transforms/NewGVN/assumes.ll index 065cc0fb62e08..ea20b38bff6af 100644 --- a/llvm/test/Transforms/NewGVN/assumes.ll +++ b/llvm/test/Transforms/NewGVN/assumes.ll @@ -1,16 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -newgvn -S | FileCheck %s -; CHECK-LABEL: @test1 -; CHECK: ret i32 %arg define i32 @test1(i32 %arg) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ARG:%.*]], 5 +; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: ret i32 [[ARG]] +; %cmp = icmp sge i32 %arg, 5 call void @llvm.assume(i1 %cmp) ret i32 %arg } -; CHECK-LABEL: @test2 -; CHECK: ret i32 %arg define i32 @test2(i32 %arg, i1 %b) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: br label [[BB:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[A:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ 2, [[BB]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARG:%.*]], [[A]] +; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: br i1 [[B:%.*]], label [[BB]], label [[END:%.*]] +; CHECK: end: +; CHECK-NEXT: ret i32 [[ARG]] +; br label %bb bb: From 4dbe82eef34e5ab8a9b0dabdbca194ff6858fc7f Mon Sep 17 00:00:00 2001 From: kuter Date: Sun, 12 Jul 2020 02:23:21 +0300 Subject: [PATCH 034/771] [Attributor] Introudce attribute seed allow list. --- llvm/include/llvm/Transforms/IPO/Attributor.h | 22 +++++++++++++ llvm/lib/Transforms/IPO/Attributor.cpp | 13 ++++++++ llvm/test/Transforms/Attributor/allow_list.ll | 33 +++++++++++++++++++ 3 files changed, 68 insertions(+) create mode 100644 llvm/test/Transforms/Attributor/allow_list.ll diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index c6261845b765a..d2666d4b86827 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -891,6 +891,13 @@ struct Attributor { // No matching attribute found, create one. // Use the static create method. auto &AA = AAType::createForPosition(IRP, *this); + + // If we are currenty seeding attributes, enforce seeding rules. + if (SeedingPeriod && !shouldSeedAttribute(AA)) { + AA.getState().indicatePessimisticFixpoint(); + return AA; + } + registerAA(AA); // For now we ignore naked and optnone functions. @@ -918,8 +925,15 @@ struct Attributor { return AA; } + // Allow seeded attributes to declare dependencies. + // Remember the seeding state. + bool OldSeedingPeriod = SeedingPeriod; + SeedingPeriod = false; + updateAA(AA); + SeedingPeriod = OldSeedingPeriod; + if (TrackDependence && AA.getState().isValidState()) recordDependence(AA, const_cast(*QueryingAA), DepClass); @@ -1345,6 +1359,10 @@ struct Attributor { ChangeStatus rewriteFunctionSignatures(SmallPtrSetImpl &ModifiedFns); + /// Check if the Attribute \p AA should be seeded. + /// See getOrCreateAAFor. + bool shouldSeedAttribute(AbstractAttribute &AA); + /// The set of all abstract attributes. ///{ using AAVector = SmallVector; @@ -1410,6 +1428,10 @@ struct Attributor { /// Invoke instructions with at least a single dead successor block. SmallVector InvokeWithDeadSuccessor; + /// Wheather attributes are being `seeded`, always false after ::run function + /// gets called \see getOrCreateAAFor. + bool SeedingPeriod = true; + /// Functions, blocks, and instructions we delete after manifest is done. /// ///{ diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp index 7f252079e0532..6e5625d26c38b 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -78,6 +78,12 @@ static cl::opt "wrappers for non-exact definitions."), cl::init(false)); +static cl::list + SeedAllowList("attributor-seed-allow-list", cl::Hidden, + cl::desc("Comma seperated list of attrbute names that are " + "allowed to be seeded."), + cl::ZeroOrMore, cl::CommaSeparated); + /// Logic operators for the change status enum class. /// ///{ @@ -1256,6 +1262,7 @@ ChangeStatus Attributor::cleanupIR() { } ChangeStatus Attributor::run() { + SeedingPeriod = false; runTillFixpoint(); ChangeStatus ManifestChange = manifestAttributes(); ChangeStatus CleanupChange = cleanupIR(); @@ -1452,6 +1459,12 @@ bool Attributor::registerFunctionSignatureRewrite( return true; } +bool Attributor::shouldSeedAttribute(AbstractAttribute &AA) { + if (SeedAllowList.size() == 0) + return true; + return std::count(SeedAllowList.begin(), SeedAllowList.end(), AA.getName()); +} + ChangeStatus Attributor::rewriteFunctionSignatures( SmallPtrSetImpl &ModifiedFns) { ChangeStatus Changed = ChangeStatus::UNCHANGED; diff --git a/llvm/test/Transforms/Attributor/allow_list.ll b/llvm/test/Transforms/Attributor/allow_list.ll new file mode 100644 index 0000000000000..7670090cb03b7 --- /dev/null +++ b/llvm/test/Transforms/Attributor/allow_list.ll @@ -0,0 +1,33 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; RUN: opt -S -passes=attributor --attributor-seed-allow-list asd < %s | FileCheck %s --check-prefixes=CHECK_DISABLED +; RUN: opt -S -passes=attributor --attributor-seed-allow-list AAValueSimplify < %s | FileCheck %s --check-prefixes=CHECK_ENABLED + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; Function Attrs: nounwind uwtable +define internal i32 @range_test(i32 %a) #0 { +; CHECK_DISABLED-LABEL: define {{[^@]+}}@range_test +; CHECK_DISABLED-SAME: (i32 [[A:%.*]]) +; CHECK_DISABLED-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A]], 100 +; CHECK_DISABLED-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i32 +; CHECK_DISABLED-NEXT: ret i32 [[TMP2]] +; + %1 = icmp sgt i32 %a, 100 + %2 = zext i1 %1 to i32 + ret i32 %2 +} + +; Function Attrs: nounwind uwtable +define i32 @range_use() #0 { +; CHECK_DISABLED-LABEL: define {{[^@]+}}@range_use() +; CHECK_DISABLED-NEXT: [[TMP1:%.*]] = call i32 @range_test(i32 123) +; CHECK_DISABLED-NEXT: ret i32 [[TMP1]] +; +; CHECK_ENABLED-LABEL: define {{[^@]+}}@range_use() +; CHECK_ENABLED-NEXT: ret i32 1 +; + %1 = call i32 @range_test(i32 123) + ret i32 %1 +} + +attributes #0 = { nounwind uwtable noinline } \ No newline at end of file From d1bcddb5c1fe7135e712b0e08874ed64c70f3e49 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 11 Jul 2020 16:44:34 -0700 Subject: [PATCH 035/771] [llvm-objdump][test] Move tests after dc4a6f5db4f0178bae43ef615cc8902c759d6195 Move RISCV/ to ELF/RISCV/ as well. --- llvm/test/tools/llvm-objdump/ARM/lit.local.cfg | 2 -- llvm/test/tools/llvm-objdump/{ => ELF}/ARM/Inputs/debug.c | 0 llvm/test/tools/llvm-objdump/{ => ELF}/ARM/Inputs/wide-char.c | 0 .../llvm-objdump/{ => ELF}/ARM/debug-vars-dwarf4-sections.s | 0 llvm/test/tools/llvm-objdump/{ => ELF}/ARM/debug-vars-dwarf4.s | 0 .../llvm-objdump/{ => ELF}/ARM/debug-vars-dwarf5-sections.s | 0 llvm/test/tools/llvm-objdump/{ => ELF}/ARM/debug-vars-dwarf5.s | 0 .../tools/llvm-objdump/{ => ELF}/ARM/debug-vars-wide-chars.s | 0 llvm/test/tools/llvm-objdump/{ => ELF}/PowerPC/debug-vars.s | 0 llvm/test/tools/llvm-objdump/{ => ELF}/RISCV/lit.local.cfg | 0 .../tools/llvm-objdump/{ => ELF}/RISCV/unknown-arch-attr.test | 0 llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg | 2 -- 12 files changed, 4 deletions(-) delete mode 100644 llvm/test/tools/llvm-objdump/ARM/lit.local.cfg rename llvm/test/tools/llvm-objdump/{ => ELF}/ARM/Inputs/debug.c (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/ARM/Inputs/wide-char.c (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/ARM/debug-vars-dwarf4-sections.s (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/ARM/debug-vars-dwarf4.s (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/ARM/debug-vars-dwarf5-sections.s (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/ARM/debug-vars-dwarf5.s (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/ARM/debug-vars-wide-chars.s (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/PowerPC/debug-vars.s (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/RISCV/lit.local.cfg (100%) rename llvm/test/tools/llvm-objdump/{ => ELF}/RISCV/unknown-arch-attr.test (100%) delete mode 100644 llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg diff --git a/llvm/test/tools/llvm-objdump/ARM/lit.local.cfg b/llvm/test/tools/llvm-objdump/ARM/lit.local.cfg deleted file mode 100644 index 236e1d3441665..0000000000000 --- a/llvm/test/tools/llvm-objdump/ARM/lit.local.cfg +++ /dev/null @@ -1,2 +0,0 @@ -if not 'ARM' in config.root.targets: - config.unsupported = True diff --git a/llvm/test/tools/llvm-objdump/ARM/Inputs/debug.c b/llvm/test/tools/llvm-objdump/ELF/ARM/Inputs/debug.c similarity index 100% rename from llvm/test/tools/llvm-objdump/ARM/Inputs/debug.c rename to llvm/test/tools/llvm-objdump/ELF/ARM/Inputs/debug.c diff --git a/llvm/test/tools/llvm-objdump/ARM/Inputs/wide-char.c b/llvm/test/tools/llvm-objdump/ELF/ARM/Inputs/wide-char.c similarity index 100% rename from llvm/test/tools/llvm-objdump/ARM/Inputs/wide-char.c rename to llvm/test/tools/llvm-objdump/ELF/ARM/Inputs/wide-char.c diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4-sections.s b/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf4-sections.s similarity index 100% rename from llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4-sections.s rename to llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf4-sections.s diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4.s b/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf4.s similarity index 100% rename from llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf4.s rename to llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf4.s diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5-sections.s b/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf5-sections.s similarity index 100% rename from llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5-sections.s rename to llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf5-sections.s diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5.s b/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf5.s similarity index 100% rename from llvm/test/tools/llvm-objdump/ARM/debug-vars-dwarf5.s rename to llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-dwarf5.s diff --git a/llvm/test/tools/llvm-objdump/ARM/debug-vars-wide-chars.s b/llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-wide-chars.s similarity index 100% rename from llvm/test/tools/llvm-objdump/ARM/debug-vars-wide-chars.s rename to llvm/test/tools/llvm-objdump/ELF/ARM/debug-vars-wide-chars.s diff --git a/llvm/test/tools/llvm-objdump/PowerPC/debug-vars.s b/llvm/test/tools/llvm-objdump/ELF/PowerPC/debug-vars.s similarity index 100% rename from llvm/test/tools/llvm-objdump/PowerPC/debug-vars.s rename to llvm/test/tools/llvm-objdump/ELF/PowerPC/debug-vars.s diff --git a/llvm/test/tools/llvm-objdump/RISCV/lit.local.cfg b/llvm/test/tools/llvm-objdump/ELF/RISCV/lit.local.cfg similarity index 100% rename from llvm/test/tools/llvm-objdump/RISCV/lit.local.cfg rename to llvm/test/tools/llvm-objdump/ELF/RISCV/lit.local.cfg diff --git a/llvm/test/tools/llvm-objdump/RISCV/unknown-arch-attr.test b/llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test similarity index 100% rename from llvm/test/tools/llvm-objdump/RISCV/unknown-arch-attr.test rename to llvm/test/tools/llvm-objdump/ELF/RISCV/unknown-arch-attr.test diff --git a/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg b/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg deleted file mode 100644 index 091332439b186..0000000000000 --- a/llvm/test/tools/llvm-objdump/PowerPC/lit.local.cfg +++ /dev/null @@ -1,2 +0,0 @@ -if not 'PowerPC' in config.root.targets: - config.unsupported = True From 77272d177a2d7128cf09dc2d27b353cc3e1ecae0 Mon Sep 17 00:00:00 2001 From: Zequan Wu Date: Sat, 11 Jul 2020 20:49:26 -0700 Subject: [PATCH 036/771] [COFF] Fix endianness of .llvm.call-graph-profile section data --- llvm/lib/MC/WinCOFFObjectWriter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index 94a8d56c55fce..4796ef531054b 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -1116,9 +1116,9 @@ uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm, for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) { uint32_t FromIndex = CGPE.From->getSymbol().getIndex(); uint32_t ToIndex = CGPE.To->getSymbol().getIndex(); - OS.write((const char *)&FromIndex, sizeof(uint32_t)); - OS.write((const char *)&ToIndex, sizeof(uint32_t)); - OS.write((const char *)&CGPE.Count, sizeof(uint64_t)); + support::endian::write(OS, FromIndex, W.Endian); + support::endian::write(OS, ToIndex, W.Endian); + support::endian::write(OS, CGPE.Count, W.Endian); } } From 6634aef71f3b5e9820d2955bd6b39d2744de06eb Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 12 Jul 2020 10:12:48 +0200 Subject: [PATCH 037/771] [SCCP] Add test for predicate info condition handling (NFC) --- .../Transforms/SCCP/predicateinfo-cond.ll | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 llvm/test/Transforms/SCCP/predicateinfo-cond.ll diff --git a/llvm/test/Transforms/SCCP/predicateinfo-cond.ll b/llvm/test/Transforms/SCCP/predicateinfo-cond.ll new file mode 100644 index 0000000000000..d8528918babed --- /dev/null +++ b/llvm/test/Transforms/SCCP/predicateinfo-cond.ll @@ -0,0 +1,110 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -ipsccp < %s | FileCheck %s + +; Test that information about the true/false value of conditions themselves +; is also used, not information implied by comparisions. + +define i32 @switch(i32 %x) { +; CHECK-LABEL: @switch( +; CHECK-NEXT: switch i32 [[X:%.*]], label [[CASE_DEFAULT:%.*]] [ +; CHECK-NEXT: i32 0, label [[CASE_0:%.*]] +; CHECK-NEXT: i32 2, label [[CASE_2:%.*]] +; CHECK-NEXT: ] +; CHECK: case.0: +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1 +; CHECK-NEXT: br label [[END:%.*]] +; CHECK: case.2: +; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], 1 +; CHECK-NEXT: br label [[END]] +; CHECK: case.default: +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[ADD]], [[CASE_0]] ], [ [[SUB]], [[CASE_2]] ], [ 1, [[CASE_DEFAULT]] ] +; CHECK-NEXT: ret i32 [[PHI]] +; + switch i32 %x, label %case.default [ + i32 0, label %case.0 + i32 2, label %case.2 + ] + +case.0: + %add = add i32 %x, 1 + br label %end + +case.2: + %sub = sub i32 %x, 1 + br label %end + +case.default: + br label %end + +end: + %phi = phi i32 [ %add, %case.0 ], [ %sub, %case.2 ], [ 1, %case.default] + ret i32 %phi +} + +define i1 @assume(i32 %x) { +; CHECK-LABEL: @assume( +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) +; CHECK-NEXT: ret i1 [[CMP]] +; + %cmp = icmp sge i32 %x, 0 + call void @llvm.assume(i1 %cmp) + ret i1 %cmp +} + +define i32 @branch(i32 %x) { +; CHECK-LABEL: @branch( +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_THEN2:%.*]] +; CHECK: if.then1: +; CHECK-NEXT: br i1 [[CMP]], label [[IF2_THEN1:%.*]], label [[IF2_THEN2:%.*]] +; CHECK: if2.then1: +; CHECK-NEXT: br label [[IF2_END:%.*]] +; CHECK: if2.then2: +; CHECK-NEXT: br label [[IF2_END]] +; CHECK: if2.end: +; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[IF2_THEN1]] ], [ 1, [[IF2_THEN2]] ] +; CHECK-NEXT: ret i32 [[PHI]] +; CHECK: if.then2: +; CHECK-NEXT: br i1 [[CMP]], label [[IF3_THEN1:%.*]], label [[IF3_THEN2:%.*]] +; CHECK: if3.then1: +; CHECK-NEXT: br label [[IF3_END:%.*]] +; CHECK: if3.then2: +; CHECK-NEXT: br label [[IF3_END]] +; CHECK: if3.end: +; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ 0, [[IF3_THEN1]] ], [ 1, [[IF3_THEN2]] ] +; CHECK-NEXT: ret i32 [[PHI2]] +; + %cmp = icmp sge i32 %x, 0 + br i1 %cmp, label %if.then1, label %if.then2 + +if.then1: + br i1 %cmp, label %if2.then1, label %if2.then2 + +if2.then1: + br label %if2.end + +if2.then2: + br label %if2.end + +if2.end: + %phi = phi i32 [ 0, %if2.then1 ], [ 1, %if2.then2 ] + ret i32 %phi + +if.then2: + br i1 %cmp, label %if3.then1, label %if3.then2 + +if3.then1: + br label %if3.end + +if3.then2: + br label %if3.end + +if3.end: + %phi2 = phi i32 [ 0, %if3.then1 ], [ 1, %if3.then2 ] + ret i32 %phi2 +} + +declare void @llvm.assume(i1) From 66f1dcd872dba189ee054fb016f4bff535fb5afc Mon Sep 17 00:00:00 2001 From: Ten Tzen Date: Sun, 12 Jul 2020 01:37:56 -0700 Subject: [PATCH 038/771] [Windows SEH] Fix the frame-ptr of a nested-filter within a _finally This change fixed a SEH bug (exposed by test58 & test61 in MSVC test xcpt4u.c); when an Except-filter is located inside a finally, the frame-pointer generated today via intrinsic @llvm.eh.recoverfp is the frame-pointer of the immediate parent _finally, not the frame-ptr of outermost host function. The fix is to retrieve the Establisher's frame-pointer that was previously saved in parent's frame. The prolog of a filter inside a _finally should be like code below: %0 = call i8* @llvm.eh.recoverfp(i8* bitcast (@"?fin$0@0@main@@"), i8*%frame_pointer) %1 = call i8* @llvm.localrecover(i8* bitcast (@"?fin$0@0@main@@"), i8*%0, i32 0) %2 = bitcast i8* %1 to i8** %3 = load i8*, i8** %2, align 8 Differential Revision: https://reviews.llvm.org/D77982 --- clang/lib/CodeGen/CGException.cpp | 43 +++++++++++++++++++ clang/lib/CodeGen/CodeGenFunction.h | 3 ++ .../CodeGen/windows-seh-filter-inFinally.c | 36 ++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 clang/test/CodeGen/windows-seh-filter-inFinally.c diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 2494f38b3159c..bdf70252b5ade 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -1815,6 +1815,48 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF, llvm::Constant *ParentI8Fn = llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryFP}); + + // if the parent is a _finally, the passed-in ParentFP is the FP + // of parent _finally, not Establisher's FP (FP of outermost function). + // Establkisher FP is 2nd paramenter passed into parent _finally. + // Fortunately, it's always saved in parent's frame. The following + // code retrieves it, and escapes it so that spill instruction won't be + // optimized away. + if (ParentCGF.ParentCGF != nullptr) { + // Locate and escape Parent's frame_pointer.addr alloca + // Depending on target, should be 1st/2nd one in LocalDeclMap. + // Let's just scan for ImplicitParamDecl with VoidPtrTy. + llvm::AllocaInst *FramePtrAddrAlloca = nullptr; + for (auto &I : ParentCGF.LocalDeclMap) { + const VarDecl *D = cast(I.first); + if (isa(D) && + D->getType() == getContext().VoidPtrTy) { + assert(D->getName().startswith("frame_pointer")); + FramePtrAddrAlloca = cast(I.second.getPointer()); + break; + } + } + assert(FramePtrAddrAlloca); + auto InsertPair = ParentCGF.EscapedLocals.insert( + std::make_pair(FramePtrAddrAlloca, ParentCGF.EscapedLocals.size())); + int FrameEscapeIdx = InsertPair.first->second; + + // an example of a filter's prolog:: + // %0 = call i8* @llvm.eh.recoverfp(bitcast(@"?fin$0@0@main@@"),..) + // %1 = call i8* @llvm.localrecover(bitcast(@"?fin$0@0@main@@"),..) + // %2 = bitcast i8* %1 to i8** + // %3 = load i8*, i8* *%2, align 8 + // ==> %3 is the frame-pointer of outermost host function + llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration( + &CGM.getModule(), llvm::Intrinsic::localrecover); + llvm::Constant *ParentI8Fn = + llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy); + ParentFP = Builder.CreateCall( + FrameRecoverFn, {ParentI8Fn, ParentFP, + llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)}); + ParentFP = Builder.CreateBitCast(ParentFP, CGM.VoidPtrPtrTy); + ParentFP = Builder.CreateLoad(Address(ParentFP, getPointerAlign())); + } } // Create llvm.localrecover calls for all captures. @@ -2013,6 +2055,7 @@ void CodeGenFunction::pushSEHCleanup(CleanupKind Kind, void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) { CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true); + HelperCGF.ParentCGF = this; if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) { // Outline the finally block. llvm::Function *FinallyFunc = diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index b1841d646643c..1fc2ed76ca9e6 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -264,6 +264,9 @@ class CodeGenFunction : public CodeGenTypeCache { CodeGenModule &CGM; // Per-module state. const TargetInfo &Target; + // For EH/SEH outlined funclets, this field points to parent's CGF + CodeGenFunction *ParentCGF = nullptr; + typedef std::pair ComplexPairTy; LoopInfoStack LoopStack; CGBuilderTy Builder; diff --git a/clang/test/CodeGen/windows-seh-filter-inFinally.c b/clang/test/CodeGen/windows-seh-filter-inFinally.c new file mode 100644 index 0000000000000..f9dfca14f0209 --- /dev/null +++ b/clang/test/CodeGen/windows-seh-filter-inFinally.c @@ -0,0 +1,36 @@ +// RUN: %clang_cc1 -triple x86_64-windows -fms-extensions -Wno-implicit-function-declaration -S -emit-llvm %s -o - | FileCheck %s + +// CHECK: %[[dst:[0-9-]+]] = call i8* @llvm.eh.recoverfp(i8* bitcast (void (i8, i8*)* @"?fin$0@0@main@@" to i8*), i8* %frame_pointer) +// CHECK-NEXT: %[[dst1:[0-9-]+]] = call i8* @llvm.localrecover(i8* bitcast (void (i8, i8*)* @"?fin$0@0@main@@" to i8*), i8* %[[dst]], i32 0) +// CHECK-NEXT: %[[dst2:[0-9-]+]] = bitcast i8* %[[dst1]] to i8** +// CHECK-NEXT: = load i8*, i8** %[[dst2]], align 8 + +int +main(int argc, char *argv[]) +{ + int Counter = 0; + // + // Try/except within the finally clause of a try/finally. + // + __try { + Counter -= 1; + } + __finally { + __try { + Counter += 2; + // RtlRaiseStatus(STATUS_INTEGER_OVERFLOW); + } __except(Counter) { + __try { + Counter += 3; + } + __finally { + if (abnormal_termination() == 1) { + Counter += 5; + } + } + } + } + // expect Counter == 9 + return 1; +} + From 39009a8245dae78250081b16fc679ce338af405a Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 12 Jul 2020 08:51:49 -0400 Subject: [PATCH 039/771] [DAGCombiner] tighten fast-math constraints for fma fold fadd (fma A, B, (fmul C, D)), E --> fma A, B, (fma C, D, E) This is only allowed when "reassoc" is present on the fadd. As discussed in D80801, this transform goes beyond what is allowed by "contract" FMF (-ffp-contract=fast). That is because we are fusing the trailing add of 'E' with a multiply, but without "reassoc", the code mandates that the products A*B and C*D are added together before adding in 'E'. I've added this example to the LangRef to try to clarify the meaning of "contract". If that seems reasonable, we should probably do something similar for the clang docs because there does not appear to be any formal spec for the behavior of -ffp-contract=fast. Differential Revision: https://reviews.llvm.org/D82499 --- llvm/docs/LangRef.rst | 4 +++- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 7 +++++-- llvm/test/CodeGen/AArch64/fadd-combines.ll | 9 +++++++-- llvm/test/CodeGen/X86/fma_patterns.ll | 19 +++++++++++++------ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index c2d6200e67fa8..86d315be74bcf 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2778,7 +2778,9 @@ floating-point transformations. ``contract`` Allow floating-point contraction (e.g. fusing a multiply followed by an - addition into a fused multiply-and-add). + addition into a fused multiply-and-add). This does not enable reassociating + to form arbitrary contractions. For example, ``(a*b) + (c*d) + e`` can not + be transformed into ``(a*b) + ((c*d) + e)`` to create two fma operations. ``afn`` Approximate functions - Allow substitution of approximate calculations for diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 0d84cd89f5aee..42e6e12f3f027 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -11986,6 +11986,8 @@ SDValue DAGCombiner::visitFADDForFMACombine(SDNode *N) { SDNodeFlags Flags = N->getFlags(); bool CanFuse = Options.UnsafeFPMath || isContractable(N); + bool CanReassociate = + Options.UnsafeFPMath || N->getFlags().hasAllowReassociation(); bool AllowFusionGlobally = (Options.AllowFPOpFusion == FPOpFusion::Fast || CanFuse || HasFMAD); // If the addition is not contractable, do not combine. @@ -12028,13 +12030,14 @@ SDValue DAGCombiner::visitFADDForFMACombine(SDNode *N) { // fadd (fma A, B, (fmul C, D)), E --> fma A, B, (fma C, D, E) // fadd E, (fma A, B, (fmul C, D)) --> fma A, B, (fma C, D, E) + // This requires reassociation because it changes the order of operations. SDValue FMA, E; - if (CanFuse && N0.getOpcode() == PreferredFusedOpcode && + if (CanReassociate && N0.getOpcode() == PreferredFusedOpcode && N0.getOperand(2).getOpcode() == ISD::FMUL && N0.hasOneUse() && N0.getOperand(2).hasOneUse()) { FMA = N0; E = N1; - } else if (CanFuse && N1.getOpcode() == PreferredFusedOpcode && + } else if (CanReassociate && N1.getOpcode() == PreferredFusedOpcode && N1.getOperand(2).getOpcode() == ISD::FMUL && N1.hasOneUse() && N1.getOperand(2).hasOneUse()) { FMA = N1; diff --git a/llvm/test/CodeGen/AArch64/fadd-combines.ll b/llvm/test/CodeGen/AArch64/fadd-combines.ll index 0e4f2c02c3110..2ff4858307802 100644 --- a/llvm/test/CodeGen/AArch64/fadd-combines.ll +++ b/llvm/test/CodeGen/AArch64/fadd-combines.ll @@ -207,6 +207,10 @@ define double @fadd_fma_fmul_1(double %a, double %b, double %c, double %d, doubl ret double %a2 } +; Minimum FMF - the 1st fadd is contracted because that combines +; fmul+fadd as specified by the order of operations; the 2nd fadd +; requires reassociation to fuse with c*d. + define float @fadd_fma_fmul_fmf(float %a, float %b, float %c, float %d, float %n0) nounwind { ; CHECK-LABEL: fadd_fma_fmul_fmf: ; CHECK: // %bb.0: @@ -220,13 +224,14 @@ define float @fadd_fma_fmul_fmf(float %a, float %b, float %c, float %d, float %n ret float %a2 } -; Minimum FMF, commute final add operands, change type. +; Not minimum FMF. define float @fadd_fma_fmul_2(float %a, float %b, float %c, float %d, float %n0) nounwind { ; CHECK-LABEL: fadd_fma_fmul_2: ; CHECK: // %bb.0: -; CHECK-NEXT: fmadd s2, s2, s3, s4 +; CHECK-NEXT: fmul s2, s2, s3 ; CHECK-NEXT: fmadd s0, s0, s1, s2 +; CHECK-NEXT: fadd s0, s4, s0 ; CHECK-NEXT: ret %m1 = fmul float %a, %b %m2 = fmul float %c, %d diff --git a/llvm/test/CodeGen/X86/fma_patterns.ll b/llvm/test/CodeGen/X86/fma_patterns.ll index 3049365b6f328..43b1f4a79aff8 100644 --- a/llvm/test/CodeGen/X86/fma_patterns.ll +++ b/llvm/test/CodeGen/X86/fma_patterns.ll @@ -1821,6 +1821,10 @@ define double @fadd_fma_fmul_1(double %a, double %b, double %c, double %d, doubl ret double %a2 } +; Minimum FMF - the 1st fadd is contracted because that combines +; fmul+fadd as specified by the order of operations; the 2nd fadd +; requires reassociation to fuse with c*d. + define float @fadd_fma_fmul_fmf(float %a, float %b, float %c, float %d, float %n0) nounwind { ; FMA-LABEL: fadd_fma_fmul_fmf: ; FMA: # %bb.0: @@ -1846,25 +1850,28 @@ define float @fadd_fma_fmul_fmf(float %a, float %b, float %c, float %d, float %n ret float %a2 } -; Minimum FMF, commute final add operands, change type. +; Not minimum FMF. define float @fadd_fma_fmul_2(float %a, float %b, float %c, float %d, float %n0) nounwind { ; FMA-LABEL: fadd_fma_fmul_2: ; FMA: # %bb.0: -; FMA-NEXT: vfmadd213ss {{.*#+}} xmm2 = (xmm3 * xmm2) + xmm4 -; FMA-NEXT: vfmadd213ss {{.*#+}} xmm0 = (xmm1 * xmm0) + xmm2 +; FMA-NEXT: vmulss %xmm3, %xmm2, %xmm2 +; FMA-NEXT: vfmadd231ss {{.*#+}} xmm2 = (xmm1 * xmm0) + xmm2 +; FMA-NEXT: vaddss %xmm2, %xmm4, %xmm0 ; FMA-NEXT: retq ; ; FMA4-LABEL: fadd_fma_fmul_2: ; FMA4: # %bb.0: -; FMA4-NEXT: vfmaddss {{.*#+}} xmm2 = (xmm2 * xmm3) + xmm4 +; FMA4-NEXT: vmulss %xmm3, %xmm2, %xmm2 ; FMA4-NEXT: vfmaddss {{.*#+}} xmm0 = (xmm0 * xmm1) + xmm2 +; FMA4-NEXT: vaddss %xmm0, %xmm4, %xmm0 ; FMA4-NEXT: retq ; ; AVX512-LABEL: fadd_fma_fmul_2: ; AVX512: # %bb.0: -; AVX512-NEXT: vfmadd213ss {{.*#+}} xmm2 = (xmm3 * xmm2) + xmm4 -; AVX512-NEXT: vfmadd213ss {{.*#+}} xmm0 = (xmm1 * xmm0) + xmm2 +; AVX512-NEXT: vmulss %xmm3, %xmm2, %xmm2 +; AVX512-NEXT: vfmadd231ss {{.*#+}} xmm2 = (xmm1 * xmm0) + xmm2 +; AVX512-NEXT: vaddss %xmm2, %xmm4, %xmm0 ; AVX512-NEXT: retq %m1 = fmul float %a, %b %m2 = fmul float %c, %d From 032810f58986cd568980227c9531de91d8bcb1cd Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Sat, 11 Jul 2020 15:15:22 -0700 Subject: [PATCH 040/771] [NFC] Fix comment style in MLIR unittests to conform to LLVM coding standards. Differential Revision: https://reviews.llvm.org/D83632 --- .../Dialect/SPIRV/DeserializationTest.cpp | 10 +++--- mlir/unittests/SDBM/SDBMTest.cpp | 2 +- mlir/unittests/TableGen/EnumsGenTest.cpp | 5 ++- mlir/unittests/TableGen/FormatTest.cpp | 18 +++++----- mlir/unittests/TableGen/StructsGenTest.cpp | 34 +++++++++---------- 5 files changed, 34 insertions(+), 35 deletions(-) diff --git a/mlir/unittests/Dialect/SPIRV/DeserializationTest.cpp b/mlir/unittests/Dialect/SPIRV/DeserializationTest.cpp index a81b7741deea0..fe5632d7ae165 100644 --- a/mlir/unittests/Dialect/SPIRV/DeserializationTest.cpp +++ b/mlir/unittests/Dialect/SPIRV/DeserializationTest.cpp @@ -25,7 +25,7 @@ using namespace mlir; -// Load the SPIRV dialect +/// Load the SPIRV dialect. static DialectRegistration SPIRVRegistration; using ::testing::StrEq; @@ -159,7 +159,7 @@ TEST_F(DeserializationTest, InsufficientWordFailure) { addHeader(); binary.push_back((2u << 16) | static_cast(spirv::Opcode::OpTypeVoid)); - // Missing word for type + // Missing word for type . ASSERT_FALSE(deserialize()); expectDiagnostic("insufficient words for the last instruction"); @@ -248,7 +248,7 @@ TEST_F(DeserializationTest, FunctionMissingEndFailure) { auto voidType = addVoidType(); auto fnType = addFunctionType(voidType, {}); addFunction(voidType, fnType); - // Missing OpFunctionEnd + // Missing OpFunctionEnd. ASSERT_FALSE(deserialize()); expectDiagnostic("expected OpFunctionEnd instruction"); @@ -260,7 +260,7 @@ TEST_F(DeserializationTest, FunctionMissingParameterFailure) { auto i32Type = addIntType(32); auto fnType = addFunctionType(voidType, {i32Type}); addFunction(voidType, fnType); - // Missing OpFunctionParameter + // Missing OpFunctionParameter. ASSERT_FALSE(deserialize()); expectDiagnostic("expected OpFunctionParameter instruction"); @@ -271,7 +271,7 @@ TEST_F(DeserializationTest, FunctionMissingLabelForFirstBlockFailure) { auto voidType = addVoidType(); auto fnType = addFunctionType(voidType, {}); addFunction(voidType, fnType); - // Missing OpLabel + // Missing OpLabel. addReturn(); addFunctionEnd(); diff --git a/mlir/unittests/SDBM/SDBMTest.cpp b/mlir/unittests/SDBM/SDBMTest.cpp index e599094ee5929..61d670650b4bf 100644 --- a/mlir/unittests/SDBM/SDBMTest.cpp +++ b/mlir/unittests/SDBM/SDBMTest.cpp @@ -17,7 +17,7 @@ using namespace mlir; -// Load the SDBM dialect +/// Load the SDBM dialect. static DialectRegistration SDBMRegistration; static MLIRContext *ctx() { diff --git a/mlir/unittests/TableGen/EnumsGenTest.cpp b/mlir/unittests/TableGen/EnumsGenTest.cpp index 47f0910403b2f..a5580197a0a39 100644 --- a/mlir/unittests/TableGen/EnumsGenTest.cpp +++ b/mlir/unittests/TableGen/EnumsGenTest.cpp @@ -13,12 +13,11 @@ #include "gmock/gmock.h" #include -// Pull in generated enum utility declarations +/// Pull in generated enum utility declarations and definitions. #include "EnumsGenTest.h.inc" -// And definitions #include "EnumsGenTest.cpp.inc" -// Test namespaces and enum class/utility names +/// Test namespaces and enum class/utility names. using Outer::Inner::ConvertToEnum; using Outer::Inner::ConvertToString; using Outer::Inner::StrEnum; diff --git a/mlir/unittests/TableGen/FormatTest.cpp b/mlir/unittests/TableGen/FormatTest.cpp index ee609291150c7..0cae408bc3fb8 100644 --- a/mlir/unittests/TableGen/FormatTest.cpp +++ b/mlir/unittests/TableGen/FormatTest.cpp @@ -19,14 +19,14 @@ TEST(FormatTest, EmptyFmtStr) { EXPECT_TRUE(result.empty()); } -// Allow extra unused positional parameters +/// Allow extra unused positional parameters. TEST(FormatTest, EmptyFmtStrExtraParams) { FmtContext ctx; std::string result = std::string(tgfmt("", &ctx, "a", "b", "c")); EXPECT_TRUE(result.empty()); } -// Allow unused placeholder substitution in context +/// Allow unused placeholder substitution in context. TEST(FormatTest, EmptyFmtStrPopulatedCtx) { FmtContext ctx; ctx.withBuilder("builder"); @@ -40,21 +40,21 @@ TEST(FormatTest, LiteralFmtStr) { EXPECT_THAT(result, StrEq("void foo {}")); } -// Print single dollar literally +/// Print single dollar literally. TEST(FormatTest, AdjacentDollar) { FmtContext ctx; std::string result = std::string(tgfmt("$", &ctx)); EXPECT_THAT(result, StrEq("$")); } -// Print dangling dollar literally +/// Print dangling dollar literally. TEST(FormatTest, DanglingDollar) { FmtContext ctx; std::string result = std::string(tgfmt("foo bar baz$", &ctx)); EXPECT_THAT(result, StrEq("foo bar baz$")); } -// Allow escape dollars with '$$' +/// Allow escape dollars with '$$'. TEST(FormatTest, EscapeDollars) { FmtContext ctx; std::string result = @@ -72,14 +72,14 @@ TEST(FormatTest, PositionalFmtStr) { EXPECT_THAT(result, StrEq("a b 43 d")); } -// Output the placeholder if missing substitution +/// Output the placeholder if missing substitution. TEST(FormatTest, PositionalFmtStrMissingParams) { FmtContext ctx; std::string result = std::string(tgfmt("$0 %1 $2", &ctx)); EXPECT_THAT(result, StrEq("$0 %1 $2")); } -// Allow flexible reference of positional parameters +/// Allow flexible reference of positional parameters. TEST(FormatTest, PositionalFmtStrFlexibleRef) { FmtContext ctx; std::string result = std::string(tgfmt("$2 $0 $2", &ctx, "a", "b", "c")); @@ -122,7 +122,7 @@ TEST(FormatTest, PlaceHolderMissingSubst) { EXPECT_THAT(result, StrEq("$_op")); } -// Test commonly used delimiters in C++ +/// Test commonly used delimiters in C++. TEST(FormatTest, PlaceHolderFmtStrDelimiter) { FmtContext ctx; ctx.addSubst("m", ""); @@ -130,7 +130,7 @@ TEST(FormatTest, PlaceHolderFmtStrDelimiter) { EXPECT_THAT(result, StrEq("{([])}|")); } -// Test allowed characters in placeholder symbol +/// Test allowed characters in placeholder symbol. TEST(FormatTest, CustomPlaceHolderFmtStrPlaceHolderChars) { FmtContext ctx; ctx.addSubst("m", "0 "); diff --git a/mlir/unittests/TableGen/StructsGenTest.cpp b/mlir/unittests/TableGen/StructsGenTest.cpp index 19aff1c83b0fe..c58fedb4ec4f0 100644 --- a/mlir/unittests/TableGen/StructsGenTest.cpp +++ b/mlir/unittests/TableGen/StructsGenTest.cpp @@ -17,12 +17,12 @@ namespace mlir { -// Pull in generated enum utility declarations +/// Pull in generated enum utility declarations and definitions. #include "StructAttrGenTest.h.inc" -// And definitions #include "StructAttrGenTest.cpp.inc" -// Helper that returns an example test::TestStruct for testing its -// implementation. + +/// Helper that returns an example test::TestStruct for testing its +/// implementation. static test::TestStruct getTestStruct(mlir::MLIRContext *context) { auto integerType = mlir::IntegerType::get(32, context); auto integerAttr = mlir::IntegerAttr::get(integerType, 127); @@ -39,16 +39,16 @@ static test::TestStruct getTestStruct(mlir::MLIRContext *context) { optionalAttr, context); } -// Validates that test::TestStruct::classof correctly identifies a valid -// test::TestStruct. +/// Validates that test::TestStruct::classof correctly identifies a valid +/// test::TestStruct. TEST(StructsGenTest, ClassofTrue) { mlir::MLIRContext context; auto structAttr = getTestStruct(&context); ASSERT_TRUE(test::TestStruct::classof(structAttr)); } -// Validates that test::TestStruct::classof fails when an extra attribute is in -// the class. +/// Validates that test::TestStruct::classof fails when an extra attribute is in +/// the class. TEST(StructsGenTest, ClassofExtraFalse) { mlir::MLIRContext context; mlir::DictionaryAttr structAttr = getTestStruct(&context); @@ -69,8 +69,8 @@ TEST(StructsGenTest, ClassofExtraFalse) { ASSERT_FALSE(test::TestStruct::classof(badDictionary)); } -// Validates that test::TestStruct::classof fails when a NamedAttribute has an -// incorrect name. +/// Validates that test::TestStruct::classof fails when a NamedAttribute has an +/// incorrect name. TEST(StructsGenTest, ClassofBadNameFalse) { mlir::MLIRContext context; mlir::DictionaryAttr structAttr = getTestStruct(&context); @@ -90,8 +90,8 @@ TEST(StructsGenTest, ClassofBadNameFalse) { ASSERT_FALSE(test::TestStruct::classof(badDictionary)); } -// Validates that test::TestStruct::classof fails when a NamedAttribute has an -// incorrect type. +/// Validates that test::TestStruct::classof fails when a NamedAttribute has an +/// incorrect type. TEST(StructsGenTest, ClassofBadTypeFalse) { mlir::MLIRContext context; mlir::DictionaryAttr structAttr = getTestStruct(&context); @@ -115,8 +115,8 @@ TEST(StructsGenTest, ClassofBadTypeFalse) { ASSERT_FALSE(test::TestStruct::classof(badDictionary)); } -// Validates that test::TestStruct::classof fails when a NamedAttribute is -// missing. +/// Validates that test::TestStruct::classof fails when a NamedAttribute is +/// missing. TEST(StructsGenTest, ClassofMissingFalse) { mlir::MLIRContext context; mlir::DictionaryAttr structAttr = getTestStruct(&context); @@ -132,7 +132,7 @@ TEST(StructsGenTest, ClassofMissingFalse) { ASSERT_FALSE(test::TestStruct::classof(badDictionary)); } -// Validate the accessor for the FloatAttr value. +/// Validate the accessor for the FloatAttr value. TEST(StructsGenTest, GetFloat) { mlir::MLIRContext context; auto structAttr = getTestStruct(&context); @@ -140,7 +140,7 @@ TEST(StructsGenTest, GetFloat) { EXPECT_EQ(returnedAttr.getValueAsDouble(), 0.25); } -// Validate the accessor for the IntegerAttr value. +/// Validate the accessor for the IntegerAttr value. TEST(StructsGenTest, GetInteger) { mlir::MLIRContext context; auto structAttr = getTestStruct(&context); @@ -148,7 +148,7 @@ TEST(StructsGenTest, GetInteger) { EXPECT_EQ(returnedAttr.getInt(), 127); } -// Validate the accessor for the ElementsAttr value. +/// Validate the accessor for the ElementsAttr value. TEST(StructsGenTest, GetElements) { mlir::MLIRContext context; auto structAttr = getTestStruct(&context); From be9f363704a802b10b30d853f1bb6571e5ebed94 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 12 Jul 2020 08:14:52 -0700 Subject: [PATCH 041/771] [AVRInstPrinter] printOperand: support llvm-objdump --print-imm-hex Differential Revision: https://reviews.llvm.org/D83634 --- llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp | 2 +- llvm/test/MC/AVR/hex-immediates.s | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 llvm/test/MC/AVR/hex-immediates.s diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp index 815a309a8caef..42fac5e2e000e 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp @@ -131,7 +131,7 @@ void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, O << getPrettyRegisterName(Op.getReg(), MRI); } } else if (Op.isImm()) { - O << Op.getImm(); + O << formatImm(Op.getImm()); } else { assert(Op.isExpr() && "Unknown operand kind in printOperand"); O << *Op.getExpr(); diff --git a/llvm/test/MC/AVR/hex-immediates.s b/llvm/test/MC/AVR/hex-immediates.s new file mode 100644 index 0000000000000..ca4c8b9f33551 --- /dev/null +++ b/llvm/test/MC/AVR/hex-immediates.s @@ -0,0 +1,7 @@ +; RUN: llvm-mc -filetype=obj -triple=avr %s -o %t +; RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DEC +; RUN: llvm-objdump -d --print-imm-hex %t | FileCheck %s --check-prefix=HEX + +; DEC: ldi r24, 66 +; HEX: ldi r24, 0x42 + ldi r24, 0x42 From d589372704fc7da0c143cbfe27f930a9d7dd333b Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 12 Jul 2020 17:48:05 +0200 Subject: [PATCH 042/771] [SCCP] Extend nonnull metadata test (NFC) --- llvm/test/Transforms/SCCP/metadata.ll | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/llvm/test/Transforms/SCCP/metadata.ll b/llvm/test/Transforms/SCCP/metadata.ll index 43e4c59571e9a..844e2103ae318 100644 --- a/llvm/test/Transforms/SCCP/metadata.ll +++ b/llvm/test/Transforms/SCCP/metadata.ll @@ -44,16 +44,39 @@ define i32 @load_range_single_volatile(i32* %p) { ret i32 %v } -define void @load_nonnull(i32** %p) { +define void @load_nonnull(i32** %p, i32** %p2) { ; CHECK-LABEL: @load_nonnull( ; CHECK-NEXT: [[V:%.*]] = load i32*, i32** [[P:%.*]], align 8, !nonnull !2 +; CHECK-NEXT: [[V2:%.*]] = load i32*, i32** [[P2:%.*]], align 8, !nonnull !2 ; CHECK-NEXT: [[C1:%.*]] = icmp ne i32* [[V]], null ; CHECK-NEXT: call void @use(i1 [[C1]]) +; CHECK-NEXT: [[C2:%.*]] = icmp eq i32* [[V]], null +; CHECK-NEXT: call void @use(i1 [[C2]]) +; CHECK-NEXT: [[C3:%.*]] = icmp ne i32* null, [[V]] +; CHECK-NEXT: call void @use(i1 [[C3]]) +; CHECK-NEXT: [[C4:%.*]] = icmp eq i32* null, [[V]] +; CHECK-NEXT: call void @use(i1 [[C4]]) +; CHECK-NEXT: [[C5:%.*]] = icmp eq i32* [[V]], [[V2]] +; CHECK-NEXT: call void @use(i1 [[C5]]) +; CHECK-NEXT: [[C6:%.*]] = icmp ne i32* [[V]], [[V2]] +; CHECK-NEXT: call void @use(i1 [[C6]]) ; CHECK-NEXT: ret void ; %v = load i32*, i32** %p, !nonnull !{} + %v2 = load i32*, i32** %p2, !nonnull !{} %c1 = icmp ne i32* %v, null call void @use(i1 %c1) + %c2 = icmp eq i32* %v, null + call void @use(i1 %c2) + %c3 = icmp ne i32* null, %v + call void @use(i1 %c3) + %c4 = icmp eq i32* null, %v + call void @use(i1 %c4) + ; There is no particular relationship between two nonnull values. + %c5 = icmp eq i32* %v, %v2 + call void @use(i1 %c5) + %c6 = icmp ne i32* %v, %v2 + call void @use(i1 %c6) ret void } From 69e60c9dc76653c10c4e8f7af1743307532102eb Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Thu, 25 Jun 2020 13:57:58 +0200 Subject: [PATCH 043/771] [LLD][ELF][AVR] Implement the missing relocation types Implements the missing relocation types for AVR target. The results have been cross-checked with binutils. Original patch by LemonBoy. Some changes by me. Differential Revision: https://reviews.llvm.org/D78741 --- lld/ELF/Arch/AVR.cpp | 122 ++++++++++++++++++++++++++++++++++++++- lld/test/ELF/avr-reloc.s | 84 +++++++++++++++++++++++++++ 2 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/avr-reloc.s diff --git a/lld/ELF/Arch/AVR.cpp b/lld/ELF/Arch/AVR.cpp index 9b733837dd5d0..4513a970b32d7 100644 --- a/lld/ELF/Arch/AVR.cpp +++ b/lld/ELF/Arch/AVR.cpp @@ -54,11 +54,131 @@ AVR::AVR() { noneRel = R_AVR_NONE; } RelExpr AVR::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { - return R_ABS; + switch (type) { + case R_AVR_7_PCREL: + case R_AVR_13_PCREL: + return R_PC; + default: + return R_ABS; + } +} + +static void writeLDI(uint8_t *loc, uint64_t val) { + write16le(loc, (read16le(loc) & 0xf0f0) | (val & 0xf0) << 4 | (val & 0x0f)); } void AVR::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { switch (rel.type) { + case R_AVR_8: + checkUInt(loc, val, 8, rel); + *loc = val; + break; + case R_AVR_16: + // Note: this relocation is often used between code and data space, which + // are 0x800000 apart in the output ELF file. The bitmask cuts off the high + // bit. + write16le(loc, val & 0xffff); + break; + case R_AVR_16_PM: + checkAlignment(loc, val, 2, rel); + checkUInt(loc, val >> 1, 16, rel); + write16le(loc, val >> 1); + break; + case R_AVR_32: + checkUInt(loc, val, 32, rel); + write32le(loc, val); + break; + + case R_AVR_LDI: + checkUInt(loc, val, 8, rel); + writeLDI(loc, val & 0xff); + break; + + case R_AVR_LO8_LDI_NEG: + writeLDI(loc, -val & 0xff); + break; + case R_AVR_LO8_LDI: + writeLDI(loc, val & 0xff); + break; + case R_AVR_HI8_LDI_NEG: + writeLDI(loc, (-val >> 8) & 0xff); + break; + case R_AVR_HI8_LDI: + writeLDI(loc, (val >> 8) & 0xff); + break; + case R_AVR_HH8_LDI_NEG: + writeLDI(loc, (-val >> 16) & 0xff); + break; + case R_AVR_HH8_LDI: + writeLDI(loc, (val >> 16) & 0xff); + break; + case R_AVR_MS8_LDI_NEG: + writeLDI(loc, (-val >> 24) & 0xff); + break; + case R_AVR_MS8_LDI: + writeLDI(loc, (val >> 24) & 0xff); + break; + + case R_AVR_LO8_LDI_PM: + checkAlignment(loc, val, 2, rel); + writeLDI(loc, (val >> 1) & 0xff); + break; + case R_AVR_HI8_LDI_PM: + checkAlignment(loc, val, 2, rel); + writeLDI(loc, (val >> 9) & 0xff); + break; + case R_AVR_HH8_LDI_PM: + checkAlignment(loc, val, 2, rel); + writeLDI(loc, (val >> 17) & 0xff); + break; + + case R_AVR_LO8_LDI_PM_NEG: + checkAlignment(loc, val, 2, rel); + writeLDI(loc, (-val >> 1) & 0xff); + break; + case R_AVR_HI8_LDI_PM_NEG: + checkAlignment(loc, val, 2, rel); + writeLDI(loc, (-val >> 9) & 0xff); + break; + case R_AVR_HH8_LDI_PM_NEG: + checkAlignment(loc, val, 2, rel); + writeLDI(loc, (-val >> 17) & 0xff); + break; + + case R_AVR_PORT5: + checkUInt(loc, val, 5, rel); + write16le(loc, (read16le(loc) & 0xff07) | (val << 3)); + break; + case R_AVR_PORT6: + checkUInt(loc, val, 6, rel); + write16le(loc, (read16le(loc) & 0xf9f0) | (val & 0x30) << 5 | (val & 0x0f)); + break; + + // Since every jump destination is word aligned we gain an extra bit + case R_AVR_7_PCREL: { + checkInt(loc, val, 7, rel); + checkAlignment(loc, val, 2, rel); + const uint16_t target = (val - 2) >> 1; + write16le(loc, (read16le(loc) & 0xfc07) | ((target & 0x7f) << 3)); + break; + } + case R_AVR_13_PCREL: { + checkAlignment(loc, val, 2, rel); + const uint16_t target = (val - 2) >> 1; + write16le(loc, (read16le(loc) & 0xf000) | (target & 0xfff)); + break; + } + + case R_AVR_6: + checkInt(loc, val, 6, rel); + write16le(loc, (read16le(loc) & 0xd3f8) | (val & 0x20) << 8 | + (val & 0x18) << 7 | (val & 0x07)); + break; + case R_AVR_6_ADIW: + checkInt(loc, val, 6, rel); + write16le(loc, (read16le(loc) & 0xff30) | (val & 0x30) << 2 | (val & 0x0F)); + break; + case R_AVR_CALL: { uint16_t hi = val >> 17; uint16_t lo = val >> 1; diff --git a/lld/test/ELF/avr-reloc.s b/lld/test/ELF/avr-reloc.s new file mode 100644 index 0000000000000..49f78044068b9 --- /dev/null +++ b/lld/test/ELF/avr-reloc.s @@ -0,0 +1,84 @@ +; REQUIRES: avr +; RUN: llvm-mc -filetype=obj -triple=avr -mcpu=atmega328p %s -o %t.o +; RUN: ld.lld %t.o --defsym=a=0x12345678 --defsym=b=30 -o %t +; RUN: llvm-objdump -d --print-imm-hex %t | FileCheck %s +; RUN: llvm-objdump -s %t | FileCheck --check-prefix=HEX %s + +.section .LDI,"ax",@progbits +; CHECK-LABEL: section .LDI: +; CHECK: ldi r20, 0x78 +; CHECK-NEXT: ldi r20, 0x56 +; CHECK-NEXT: ldi r20, 0x34 +; CHECK-NEXT: ldi r20, 0x12 +; CHECK-NEXT: ldi r20, 0x3c +; CHECK-NEXT: ldi r20, 0x2b +; CHECK-NEXT: ldi r20, 0x1a +; CHECK-NEXT: ldi r20, 0xff +ldi r20, lo8(a) ; R_AVR_LO8_LDI +ldi r20, hi8(a) ; R_AVR_HI8_LDI +ldi r20, hh8(a) ; R_AVR_HH8_LDI +ldi r20, hhi8(a) ; R_AVR_MS8_LDI + +ldi r20, pm_lo8(a) ; R_AVR_LO8_LDI_PM +ldi r20, pm_hi8(a) ; R_AVR_HI8_LDI_PM +ldi r20, pm_hh8(a) ; R_AVR_HH8_LDI_PM + +ldi r20, b+225 + +.section .LDI_NEG,"ax",@progbits +; CHECK-LABEL: section .LDI_NEG: +; CHECK: ldi r20, 0x88 +; CHECK-NEXT: ldi r20, 0xa9 +; CHECK-NEXT: ldi r20, 0xcb +; CHECK-NEXT: ldi r20, 0xed +; CHECK-NEXT: ldi r20, 0xc4 +; CHECK-NEXT: ldi r20, 0xd4 +; CHECK-NEXT: ldi r20, 0xe5 +ldi r20, lo8(-(a)) ; R_AVR_LO8_LDI_NEG +ldi r20, hi8(-(a)) ; R_AVR_HI8_LDI_NEG +ldi r20, hh8(-(a)) ; R_AVR_HH8_LDI_NEG +ldi r20, hhi8(-(a)) ; R_AVR_MS8_LDI_NEG + +ldi r20, pm_lo8(-(a)) ; R_AVR_LO8_LDI_PM_NEG +ldi r20, pm_hi8(-(a)) ; R_AVR_HI8_LDI_PM_NEG +ldi r20, pm_hh8(-(a)) ; R_AVR_HH8_LDI_PM_NEG + +;; The disassembler is not yet able to decode those opcodes +;; 9e 8e std Y+30, r9 +;; 9e 8c ldd r9, Y+30 +;; 4e 96 adiw r24, 0x1e +.section .SIX,"ax",@progbits +; HEX-LABEL: section .SIX: +; HEX-NEXT: 9e8e9e8c 4e96 +std Y+b, r9 ; R_AVR_6 +ldd r9, Y+b ; R_AVR_6 +adiw r24, b ; R_AVR_6_ADIW + +.section .PORT,"ax",@progbits +; CHECK-LABEL: section .PORT: +; CHECK: in r20, 0x1e +; CHECK-NEXT: sbic 0x1e, 0x1 +in r20, b ; R_AVR_PORT6 +sbic b, 1 ; R_AVR_PORT5 + +;; The disassembler is not yet able to decode those opcodes +;; 0f c0 rjmp .+30 +;; ee cf rjmp .-36 +;; 69 f0 breq .+26 +;; 61 f3 breq .-40 +.section .PCREL,"ax",@progbits +; HEX-LABEL: section .PCREL: +; HEX-NEXT: 0fc0eecf 69f061f3 +foo: +rjmp foo + 32 ; R_AVR_13_PCREL +rjmp foo - 32 ; R_AVR_13_PCREL +breq foo + 32 ; R_AVR_7_PCREL +breq foo - 32 ; R_AVR_7_PCREL + +.section .DATA,"ax",@progbits +; HEX-LABEL: section .DATA: +; HEX-NEXT: {{.*}} 1e1e000f 00785634 12 +.byte b ; R_AVR_8 +.short b ; R_AVR_16 +.short gs(b) ; R_AVR_16_PM +.long a ; R_AVR_32 From 152a9fef1b3b44f2c224cb8096b3d649279f2578 Mon Sep 17 00:00:00 2001 From: Yonghong Song Date: Sat, 11 Jul 2020 19:08:21 -0700 Subject: [PATCH 044/771] BPF: permit .maps section variables with typedef type Currently, llvm when see a global variable in .maps section, it ensures its type must be a struct type. Then pointee will be further evaluated for the structure members. In normal cases, the pointee type will be skipped. Although this is what current all bpf programs are doing, but it is a little bit restrictive. For example, it is legitimate for users to have: typedef struct { int key_size; int value_size; } __map_t; __map_t map __attribute__((section(".maps"))); This patch lifts this restriction and typedef of a struct type is also allowed for .maps section variables. To avoid create unnecessary fixup entries when traversal started with typedef/struct type, the new implementation first traverse all map struct members and then traverse the typedef/struct type. This way, in internal BTFDebug implementation, no fixup entries are generated. Two new unit tests are added for typedef and const struct in .maps section. Also tested with kernel bpf selftests. Differential Revision: https://reviews.llvm.org/D83638 --- llvm/lib/Target/BPF/BTFDebug.cpp | 32 +++++---- llvm/test/CodeGen/BPF/BTF/map-def-2.ll | 90 ++++++++++++++++++++++++++ llvm/test/CodeGen/BPF/BTF/map-def-3.ll | 65 +++++++++++++++++++ llvm/test/CodeGen/BPF/BTF/map-def.ll | 58 ++++++++--------- 4 files changed, 199 insertions(+), 46 deletions(-) create mode 100644 llvm/test/CodeGen/BPF/BTF/map-def-2.ll create mode 100644 llvm/test/CodeGen/BPF/BTF/map-def-3.ll diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp index 6ada75adba969..4510e93574892 100644 --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -664,7 +664,17 @@ void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) { return; } - // MapDef type is a struct type + // MapDef type may be a struct type or a non-pointer derived type + const DIType *OrigTy = Ty; + while (auto *DTy = dyn_cast(Ty)) { + auto Tag = DTy->getTag(); + if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && + Tag != dwarf::DW_TAG_volatile_type && + Tag != dwarf::DW_TAG_restrict_type) + break; + Ty = DTy->getBaseType(); + } + const auto *CTy = dyn_cast(Ty); if (!CTy) return; @@ -673,27 +683,15 @@ void BTFDebug::visitMapDefType(const DIType *Ty, uint32_t &TypeId) { if (Tag != dwarf::DW_TAG_structure_type || CTy->isForwardDecl()) return; - // Record this type + // Visit all struct members to ensure pointee type is visited const DINodeArray Elements = CTy->getElements(); - bool HasBitField = false; - for (const auto *Element : Elements) { - auto E = cast(Element); - if (E->isBitField()) { - HasBitField = true; - break; - } - } - - auto TypeEntry = - std::make_unique(CTy, true, HasBitField, Elements.size()); - StructTypes.push_back(TypeEntry.get()); - TypeId = addType(std::move(TypeEntry), CTy); - - // Visit all struct members for (const auto *Element : Elements) { const auto *MemberType = cast(Element); visitTypeEntry(MemberType->getBaseType()); } + + // Visit this type, struct or a const/typedef/volatile/restrict type + visitTypeEntry(OrigTy, TypeId, false, false); } /// Read file contents from the actual file or from the source diff --git a/llvm/test/CodeGen/BPF/BTF/map-def-2.ll b/llvm/test/CodeGen/BPF/BTF/map-def-2.ll new file mode 100644 index 0000000000000..bf3c4a7961fbf --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/map-def-2.ll @@ -0,0 +1,90 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; +; Source code: +; struct key_type { +; int a1; +; }; +; typedef struct map_type { +; struct key_type *key; +; } _map_type; +; typedef _map_type __map_type; +; __map_type __attribute__((section(".maps"))) hash_map; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t2.c + +%struct.map_type = type { %struct.key_type* } +%struct.key_type = type { i32 } + +@hash_map = dso_local local_unnamed_addr global %struct.map_type zeroinitializer, section ".maps", align 8, !dbg !0 + +; CHECK: .long 0 # BTF_KIND_PTR(id = 1) +; CHECK-NEXT: .long 33554432 # 0x2000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_STRUCT(id = 2) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 10 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 13 # BTF_KIND_INT(id = 3) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 17 # BTF_KIND_TYPEDEF(id = 4) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 28 # BTF_KIND_TYPEDEF(id = 5) +; CHECK-NEXT: .long 134217728 # 0x8000000 +; CHECK-NEXT: .long 6 +; CHECK-NEXT: .long 38 # BTF_KIND_STRUCT(id = 6) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 8 +; CHECK-NEXT: .long 47 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 51 # BTF_KIND_VAR(id = 7) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 60 # BTF_KIND_DATASEC(id = 8) +; CHECK-NEXT: .long 251658241 # 0xf000001 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 7 +; CHECK-NEXT: .long hash_map +; CHECK-NEXT: .long 8 + +; CHECK: .ascii "key_type" # string offset=1 +; CHECK: .ascii "a1" # string offset=10 +; CHECK: .ascii "int" # string offset=13 +; CHECK: .ascii "__map_type" # string offset=17 +; CHECK: .ascii "_map_type" # string offset=28 +; CHECK: .ascii "map_type" # string offset=38 +; CHECK: .ascii "key" # string offset=47 +; CHECK: .ascii "hash_map" # string offset=51 +; CHECK: .ascii ".maps" # string offset=60 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!16, !17, !18} +!llvm.ident = !{!19} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "hash_map", scope: !2, file: !3, line: 8, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git b8409c03ed90807f3d49c7d98dceea98cf461f7a)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "t2.c", directory: "/tmp/home/yhs/tmp1") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_typedef, name: "__map_type", file: !3, line: 7, baseType: !7) +!7 = !DIDerivedType(tag: DW_TAG_typedef, name: "_map_type", file: !3, line: 6, baseType: !8) +!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_type", file: !3, line: 4, size: 64, elements: !9) +!9 = !{!10} +!10 = !DIDerivedType(tag: DW_TAG_member, name: "key", scope: !8, file: !3, line: 5, baseType: !11, size: 64) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "key_type", file: !3, line: 1, size: 32, elements: !13) +!13 = !{!14} +!14 = !DIDerivedType(tag: DW_TAG_member, name: "a1", scope: !12, file: !3, line: 2, baseType: !15, size: 32) +!15 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!16 = !{i32 7, !"Dwarf Version", i32 4} +!17 = !{i32 2, !"Debug Info Version", i32 3} +!18 = !{i32 1, !"wchar_size", i32 4} +!19 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git b8409c03ed90807f3d49c7d98dceea98cf461f7a)"} diff --git a/llvm/test/CodeGen/BPF/BTF/map-def-3.ll b/llvm/test/CodeGen/BPF/BTF/map-def-3.ll new file mode 100644 index 0000000000000..e05470782ec26 --- /dev/null +++ b/llvm/test/CodeGen/BPF/BTF/map-def-3.ll @@ -0,0 +1,65 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s +; +; Source code: +; struct key_type { +; int a1; +; }; +; const struct key_type __attribute__((section(".maps"))) hash_map; +; Compilation flag: +; clang -target bpf -O2 -g -S -emit-llvm t3.c + +%struct.key_type = type { i32 } + +@hash_map = dso_local local_unnamed_addr constant %struct.key_type zeroinitializer, section ".maps", align 4, !dbg !0 + +; CHECK: .long 1 # BTF_KIND_INT(id = 1) +; CHECK-NEXT: .long 16777216 # 0x1000000 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 16777248 # 0x1000020 +; CHECK-NEXT: .long 0 # BTF_KIND_CONST(id = 2) +; CHECK-NEXT: .long 167772160 # 0xa000000 +; CHECK-NEXT: .long 3 +; CHECK-NEXT: .long 5 # BTF_KIND_STRUCT(id = 3) +; CHECK-NEXT: .long 67108865 # 0x4000001 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 14 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 17 # BTF_KIND_VAR(id = 4) +; CHECK-NEXT: .long 234881024 # 0xe000000 +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 26 # BTF_KIND_DATASEC(id = 5) +; CHECK-NEXT: .long 251658241 # 0xf000001 +; CHECK-NEXT: .long 0 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long hash_map +; CHECK-NEXT: .long 4 + +; CHECK: .ascii "int" # string offset=1 +; CHECK: .ascii "key_type" # string offset=5 +; CHECK: .ascii "a1" # string offset=14 +; CHECK: .ascii "hash_map" # string offset=17 +; CHECK: .ascii ".maps" # string offset=26 + + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!11, !12, !13} +!llvm.ident = !{!14} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "hash_map", scope: !2, file: !3, line: 4, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 11.0.0 (https://github.com/llvm/llvm-project.git 5bd074629f00d4798674b411cf00216f38016483)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "t3.c", directory: "/tmp/home/yhs/tmp1") +!4 = !{} +!5 = !{!0} +!6 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !7) +!7 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "key_type", file: !3, line: 1, size: 32, elements: !8) +!8 = !{!9} +!9 = !DIDerivedType(tag: DW_TAG_member, name: "a1", scope: !7, file: !3, line: 2, baseType: !10, size: 32) +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{i32 7, !"Dwarf Version", i32 4} +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = !{i32 1, !"wchar_size", i32 4} +!14 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git 5bd074629f00d4798674b411cf00216f38016483)"} diff --git a/llvm/test/CodeGen/BPF/BTF/map-def.ll b/llvm/test/CodeGen/BPF/BTF/map-def.ll index cf777880efa17..e12cde3ef98ae 100644 --- a/llvm/test/CodeGen/BPF/BTF/map-def.ll +++ b/llvm/test/CodeGen/BPF/BTF/map-def.ll @@ -28,41 +28,41 @@ ; CHECK-NEXT: .long 168 ; CHECK-NEXT: .long 168 ; CHECK-NEXT: .long 65 -; CHECK-NEXT: .long 1 # BTF_KIND_STRUCT(id = 1) -; CHECK-NEXT: .long 67108866 # 0x4000002 -; CHECK-NEXT: .long 16 -; CHECK-NEXT: .long 10 -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long 0 # 0x0 -; CHECK-NEXT: .long 14 -; CHECK-NEXT: .long 5 -; CHECK-NEXT: .long 64 # 0x40 -; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 2) +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 1) ; CHECK-NEXT: .long 33554432 # 0x2000000 -; CHECK-NEXT: .long 3 -; CHECK-NEXT: .long 20 # BTF_KIND_STRUCT(id = 3) +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long 1 # BTF_KIND_STRUCT(id = 2) ; CHECK-NEXT: .long 67108866 # 0x4000002 ; CHECK-NEXT: .long 8 -; CHECK-NEXT: .long 29 -; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 10 +; CHECK-NEXT: .long 3 ; CHECK-NEXT: .long 0 # 0x0 -; CHECK-NEXT: .long 31 -; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 12 +; CHECK-NEXT: .long 3 ; CHECK-NEXT: .long 32 # 0x20 -; CHECK-NEXT: .long 33 # BTF_KIND_INT(id = 4) +; CHECK-NEXT: .long 14 # BTF_KIND_INT(id = 3) ; CHECK-NEXT: .long 16777216 # 0x1000000 ; CHECK-NEXT: .long 4 ; CHECK-NEXT: .long 16777248 # 0x1000020 -; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 5) +; CHECK-NEXT: .long 0 # BTF_KIND_PTR(id = 4) ; CHECK-NEXT: .long 33554432 # 0x2000000 -; CHECK-NEXT: .long 6 -; CHECK-NEXT: .long 37 # BTF_KIND_INT(id = 6) +; CHECK-NEXT: .long 5 +; CHECK-NEXT: .long 18 # BTF_KIND_INT(id = 5) ; CHECK-NEXT: .long 16777216 # 0x1000000 ; CHECK-NEXT: .long 4 ; CHECK-NEXT: .long 32 # 0x20 +; CHECK-NEXT: .long 31 # BTF_KIND_STRUCT(id = 6) +; CHECK-NEXT: .long 67108866 # 0x4000002 +; CHECK-NEXT: .long 16 +; CHECK-NEXT: .long 40 +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 0 # 0x0 +; CHECK-NEXT: .long 44 +; CHECK-NEXT: .long 4 +; CHECK-NEXT: .long 64 # 0x40 ; CHECK-NEXT: .long 50 # BTF_KIND_VAR(id = 7) ; CHECK-NEXT: .long 234881024 # 0xe000000 -; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long 6 ; CHECK-NEXT: .long 1 ; CHECK-NEXT: .long 59 # BTF_KIND_DATASEC(id = 8) ; CHECK-NEXT: .long 251658241 # 0xf000001 @@ -71,21 +71,21 @@ ; CHECK-NEXT: .long hash_map ; CHECK-NEXT: .long 16 ; CHECK-NEXT: .byte 0 # string offset=0 -; CHECK-NEXT: .ascii "map_type" # string offset=1 +; CHECK-NEXT: .ascii "key_type" # string offset=1 ; CHECK-NEXT: .byte 0 -; CHECK-NEXT: .ascii "key" # string offset=10 +; CHECK-NEXT: .byte 97 # string offset=10 ; CHECK-NEXT: .byte 0 -; CHECK-NEXT: .ascii "value" # string offset=14 +; CHECK-NEXT: .byte 98 # string offset=12 ; CHECK-NEXT: .byte 0 -; CHECK-NEXT: .ascii "key_type" # string offset=20 +; CHECK-NEXT: .ascii "int" # string offset=14 ; CHECK-NEXT: .byte 0 -; CHECK-NEXT: .byte 97 # string offset=29 +; CHECK-NEXT: .ascii "unsigned int" # string offset=18 ; CHECK-NEXT: .byte 0 -; CHECK-NEXT: .byte 98 # string offset=31 +; CHECK-NEXT: .ascii "map_type" # string offset=31 ; CHECK-NEXT: .byte 0 -; CHECK-NEXT: .ascii "int" # string offset=33 +; CHECK-NEXT: .ascii "key" # string offset=40 ; CHECK-NEXT: .byte 0 -; CHECK-NEXT: .ascii "unsigned int" # string offset=37 +; CHECK-NEXT: .ascii "value" # string offset=44 ; CHECK-NEXT: .byte 0 ; CHECK-NEXT: .ascii "hash_map" # string offset=50 ; CHECK-NEXT: .byte 0 From 82a5157ff1650e3366f7a9c619269766ad1d5e93 Mon Sep 17 00:00:00 2001 From: Ayal Zaks Date: Thu, 9 Jul 2020 12:57:45 +0300 Subject: [PATCH 045/771] [LV] Fixing versioning-for-unit-stide of loops with small trip count This patch fixes D81345 and PR46652. If a loop with a small trip count is compiled w/o -Os/-Oz, Loop Access Analysis still generates runtime checks for unit strides that will version the loop. In such cases, the loop vectorizer should either re-run the analysis or bail-out from vectorizing the loop, as done prior to D81345. The latter is applied for now as the former requires refactoring. Differential Revision: https://reviews.llvm.org/D83470 --- .../Transforms/Vectorize/LoopVectorize.cpp | 10 +++++-- llvm/test/Transforms/LoopVectorize/optsize.ll | 26 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 10e690d56ffd1..35af8e4257789 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -4949,8 +4949,14 @@ bool LoopVectorizationCostModel::runtimeChecksRequired() { return true; } - assert(Legal->getLAI()->getSymbolicStrides().empty() && - "Specializing for stride == 1 under -Os/-Oz"); + // FIXME: Avoid specializing for stride==1 instead of bailing out. + if (!Legal->getLAI()->getSymbolicStrides().empty()) { + reportVectorizationFailure("Runtime stride check for small trip count", + "runtime stride == 1 checks needed. Enable vectorization of " + "this loop without such check by compiling with -Os/-Oz", + "CantVersionLoopWithOptForSize", ORE, TheLoop); + return true; + } return false; } diff --git a/llvm/test/Transforms/LoopVectorize/optsize.ll b/llvm/test/Transforms/LoopVectorize/optsize.ll index 8def1ab0a0e83..0e88f362746fb 100644 --- a/llvm/test/Transforms/LoopVectorize/optsize.ll +++ b/llvm/test/Transforms/LoopVectorize/optsize.ll @@ -221,6 +221,32 @@ for.end: ret void } +; PR46652: Check that the need for stride==1 check prevents vectorizing a loop +; having tiny trip count, when compiling w/o -Os/-Oz. +; CHECK-LABEL: @pr46652 +; CHECK-NOT: vector.scevcheck +; CHECK-NOT: vector.body +; CHECK-LABEL: for.body + +@g = external global [1 x i16], align 1 + +define void @pr46652(i16 %stride) { +entry: + br label %for.body + +for.body: ; preds = %for.body, %entry + %l1.02 = phi i16 [ 1, %entry ], [ %inc9, %for.body ] + %mul = mul nsw i16 %l1.02, %stride + %arrayidx6 = getelementptr inbounds [1 x i16], [1 x i16]* @g, i16 0, i16 %mul + %0 = load i16, i16* %arrayidx6, align 1 + %inc9 = add nuw nsw i16 %l1.02, 1 + %exitcond.not = icmp eq i16 %inc9, 16 + br i1 %exitcond.not, label %for.end, label %for.body + +for.end: ; preds = %for.body + ret void +} + !llvm.module.flags = !{!0} !0 = !{i32 1, !"ProfileSummary", !1} !1 = !{!2, !3, !4, !5, !6, !7, !8, !9} From 65dc97b79eb1979c54e7e17c411ea5f58f8dcc9c Mon Sep 17 00:00:00 2001 From: mydeveloperday Date: Sun, 12 Jul 2020 18:43:14 +0100 Subject: [PATCH 046/771] [clang-format] PR46609 clang-format does not obey `PointerAlignment: Right` for ellipsis in declarator for pack Summary: https://bugs.llvm.org/show_bug.cgi?id=46609 Ensure `*...` obey they left/middle/right rules of Pointer alignment Reviewed By: curdeius Differential Revision: https://reviews.llvm.org/D83564 --- clang/lib/Format/TokenAnnotator.cpp | 5 +++++ clang/unittests/Format/FormatTest.cpp | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index a74015d3b4dc3..7f8e351265127 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2844,6 +2844,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, Left.Previous && !Left.Previous->isOneOf(tok::l_paren, tok::coloncolon, tok::l_square)); + // Ensure right pointer alignement with ellipsis e.g. int *...P + if (Left.is(tok::ellipsis) && Left.Previous && + Left.Previous->isOneOf(tok::star, tok::amp, tok::ampamp)) + return Style.PointerAlignment != FormatStyle::PAS_Right; + if (Right.is(tok::star) && Left.is(tok::l_paren)) return false; if (Left.is(tok::star) && Right.isOneOf(tok::star, tok::amp, tok::ampamp)) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index ff9a64e81d5b5..6ac3ffbffd1c8 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -5325,7 +5325,7 @@ TEST_F(FormatTest, DeductionGuides) { verifyFormat("template S(Ts...) -> S;"); verifyFormat( "template \n" - "array(T &&... t) -> array, sizeof...(T)>;"); + "array(T &&...t) -> array, sizeof...(T)>;"); verifyFormat("template A() -> Afoo<3>())>;"); verifyFormat("template A() -> A>)>;"); verifyFormat("template A() -> Afoo<1>)>;"); @@ -8179,13 +8179,20 @@ TEST_F(FormatTest, AttributePenaltyBreaking) { } TEST_F(FormatTest, UnderstandsEllipsis) { + FormatStyle Style = getLLVMStyle(); verifyFormat("int printf(const char *fmt, ...);"); verifyFormat("template void Foo(Ts... ts) { Foo(ts...); }"); - verifyFormat("template void Foo(Ts *... ts) {}"); + verifyFormat("template void Foo(Ts *...ts) {}"); + + verifyFormat("template a;", Style); + + Style.PointerAlignment = FormatStyle::PAS_Left; + verifyFormat("template void Foo(Ts*... ts) {}", Style); + + verifyFormat("template a;", Style); - FormatStyle PointersLeft = getLLVMStyle(); - PointersLeft.PointerAlignment = FormatStyle::PAS_Left; - verifyFormat("template void Foo(Ts*... ts) {}", PointersLeft); + Style.PointerAlignment = FormatStyle::PAS_Middle; + verifyFormat("template a;", Style); } TEST_F(FormatTest, AdaptivelyFormatsPointersAndReferences) { From 04013a07ac3b67eb176ddfd1ddaeda41415c038f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 12 Jul 2020 10:29:45 -0700 Subject: [PATCH 047/771] [X86] Fix two places that appear to misuse peekThroughOneUseBitcasts peekThroughOneUseBitcasts checks the use count of the operand of the bitcast. Not the bitcast itself. So I think that means we need to do any outside haseOneUse checks before calling the function not after. I was working on another patch where I misused the function and did a very quick audit to see if I there were other similar mistakes. Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D83598 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 721b262aa433b..7657125e1e5ad 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -36464,9 +36464,9 @@ static SDValue combineTargetShuffle(SDValue N, SelectionDAG &DAG, (V.getOpcode() == X86ISD::PSHUFLW || V.getOpcode() == X86ISD::PSHUFHW) && V.getOpcode() != N.getOpcode() && - V.hasOneUse()) { + V.hasOneUse() && V.getOperand(0).hasOneUse()) { SDValue D = peekThroughOneUseBitcasts(V.getOperand(0)); - if (D.getOpcode() == X86ISD::PSHUFD && D.hasOneUse()) { + if (D.getOpcode() == X86ISD::PSHUFD) { SmallVector VMask = getPSHUFShuffleMask(V); SmallVector DMask = getPSHUFShuffleMask(D); int NOffset = N.getOpcode() == X86ISD::PSHUFLW ? 0 : 4; @@ -36903,10 +36903,11 @@ static SDValue combineShuffle(SDNode *N, SelectionDAG &DAG, // insert into a zero vector. This helps get VZEXT_MOVL closer to // scalar_to_vectors where 256/512 are canonicalized to an insert and a // 128-bit scalar_to_vector. This reduces the number of isel patterns. - if (N->getOpcode() == X86ISD::VZEXT_MOVL && !DCI.isBeforeLegalizeOps()) { + if (N->getOpcode() == X86ISD::VZEXT_MOVL && !DCI.isBeforeLegalizeOps() && + N->getOperand(0).hasOneUse()) { SDValue V = peekThroughOneUseBitcasts(N->getOperand(0)); - if (V.getOpcode() == ISD::INSERT_SUBVECTOR && V.hasOneUse() && + if (V.getOpcode() == ISD::INSERT_SUBVECTOR && V.getOperand(0).isUndef() && isNullConstant(V.getOperand(2))) { SDValue In = V.getOperand(1); MVT SubVT = From f8f007e378e1ed84fadf281f05166a4463a79316 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 12 Jul 2020 10:30:27 -0700 Subject: [PATCH 048/771] [X86] Consistently use 128 as the PSHUFB/VPPERM index for zero Bit 7 of the index controls zeroing, the other bits are ignored when bit 7 is set. Shuffle lowering was using 128 and shuffle combining was using 255. Seems like we should be consistent. This patch changes shuffle combining to use 128 to match lowering. Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D83587 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 4 ++-- llvm/test/CodeGen/X86/vector-trunc.ll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 7657125e1e5ad..450927aaf5cc7 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -35043,7 +35043,7 @@ static SDValue combineX86ShuffleChain(ArrayRef Inputs, SDValue Root, continue; } if (M == SM_SentinelZero) { - PSHUFBMask.push_back(DAG.getConstant(255, DL, MVT::i8)); + PSHUFBMask.push_back(DAG.getConstant(0x80, DL, MVT::i8)); continue; } M = Ratio * M + i % Ratio; @@ -35074,7 +35074,7 @@ static SDValue combineX86ShuffleChain(ArrayRef Inputs, SDValue Root, continue; } if (M == SM_SentinelZero) { - VPPERMMask.push_back(DAG.getConstant(128, DL, MVT::i8)); + VPPERMMask.push_back(DAG.getConstant(0x80, DL, MVT::i8)); continue; } M = Ratio * M + i % Ratio; diff --git a/llvm/test/CodeGen/X86/vector-trunc.ll b/llvm/test/CodeGen/X86/vector-trunc.ll index a5f6be558e8cf..1d596f5db3aeb 100644 --- a/llvm/test/CodeGen/X86/vector-trunc.ll +++ b/llvm/test/CodeGen/X86/vector-trunc.ll @@ -456,7 +456,7 @@ define <8 x i16> @trunc8i32_8i16_lshr(<8 x i32> %a) { ; ; SSSE3-LABEL: trunc8i32_8i16_lshr: ; SSSE3: # %bb.0: # %entry -; SSSE3-NEXT: movdqa {{.*#+}} xmm2 = [2,3,6,7,10,11,14,15,10,11,14,15,14,15,255,255] +; SSSE3-NEXT: movdqa {{.*#+}} xmm2 = [2,3,6,7,10,11,14,15,10,11,14,15,14,15,128,128] ; SSSE3-NEXT: pshufb %xmm2, %xmm1 ; SSSE3-NEXT: pshufb %xmm2, %xmm0 ; SSSE3-NEXT: punpcklqdq {{.*#+}} xmm0 = xmm0[0],xmm1[0] From 7a1bcf9f9a95fca9dcf8e42f8eb845db3643fffb Mon Sep 17 00:00:00 2001 From: mydeveloperday Date: Sun, 12 Jul 2020 18:57:14 +0100 Subject: [PATCH 049/771] [polly] NFC clang-format change following D83564 --- polly/lib/Analysis/ScopDetection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp index abe189f3e890a..53d0b705c055d 100644 --- a/polly/lib/Analysis/ScopDetection.cpp +++ b/polly/lib/Analysis/ScopDetection.cpp @@ -383,7 +383,7 @@ ScopDetection::ScopDetection(Function &F, const DominatorTree &DT, template inline bool ScopDetection::invalid(DetectionContext &Context, bool Assert, - Args &&... Arguments) const { + Args &&...Arguments) const { if (!Context.Verifying) { RejectLog &Log = Context.Log; std::shared_ptr RejectReason = std::make_shared(Arguments...); From f4d29d6e8c43cfd924d9d7cc1ac0c269b2788e75 Mon Sep 17 00:00:00 2001 From: Sjoerd Meijer Date: Thu, 9 Jul 2020 13:30:50 +0100 Subject: [PATCH 050/771] [Matrix] Tighten LangRef definitions and Verifier checks. This tightens the matrix intrinsic definitions in LLVM LangRef and adds correspondings checks to the IR Verifier. Differential Revision: https://reviews.llvm.org/D83477 --- llvm/docs/LangRef.rst | 96 ++++++++++-------- llvm/lib/IR/Verifier.cpp | 59 ++++++++++-- llvm/test/Verifier/matrix-intrinsics.ll | 123 +++++++++++++++++++++--- 3 files changed, 217 insertions(+), 61 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 86d315be74bcf..02c92f1a4daa6 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -15524,6 +15524,7 @@ The argument to this intrinsic must be a vector of floating-point values. Syntax: """"""" +This is an overloaded intrinsic. :: @@ -15548,17 +15549,20 @@ Matrix Intrinsics ----------------- Operations on matrixes requiring shape information (like number of rows/columns -or the memory layout) can be expressed using the matrix intrinsics. Matrixes are -embedded in a flat vector and the intrinsics take the dimensions as arguments. -Currently column-major layout is assumed. The intrinsics support both integer -and floating point matrixes. +or the memory layout) can be expressed using the matrix intrinsics. These +intrinsics require matrix dimensions to be passed as immediate arguments, and +matrixes are passed and returned as vectors. This means that for a ``R`` x +``C`` matrix, element ``i`` of column ``j`` is at index ``j * R + i`` in the +corresponding vector, with indices starting at 0. Currently column-major layout +is assumed. The intrinsics support both integer and floating point matrixes. '``llvm.matrix.transpose.*``' Intrinsic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: """"""" +This is an overloaded intrinsic. :: @@ -15567,21 +15571,24 @@ Syntax: Overview: """"""""" -The '``llvm.matrix.transpose.*``' intrinsic treats %In as containing a matrix -with rows and columns and returns the transposed matrix embedded in -the result vector. +The '``llvm.matrix.transpose.*``' intrinsics treat %In as a x matrix +and return the transposed matrix in the result vector. Arguments: """""""""" -The and arguments must be constant integers. The vector argument -%In and the returned vector must have * elements. +First argument %In is vector that corresponds to a x matrix. +Thus, arguments and correspond to the number of rows and columns, +respectively, and must be positive, constant integers. The returned vector must +have * elements, and have the same float or integer element type +as %In. '``llvm.matrix.multiply.*``' Intrinsic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: """"""" +This is an overloaded intrinsic. :: @@ -15590,18 +15597,19 @@ Syntax: Overview: """"""""" -The '``llvm.matrix.multiply.*``' intrinsic treats %A as a matrix with -rows and columns, %B as a matrix with rows and -columns and multiplies them. The result matrix is returned embedded in the -result vector. +The '``llvm.matrix.multiply.*``' intrinsics treat %A as a x +matrix, %B as a x matrix, and multiplies them. The result +matrix is returned in the result vector. Arguments: """""""""" -The , and arguments must be constant -integers. The vector argument %A must have * elements, %B -must have * elements and the returned vector must have - * elements. +The first vector argument %A corresponds to a matrix with * +elements, and the second argument %B to a matrix with * +elements. Arguments , and must be positive, +constant integers. The returned vector must have * +elements. Vectors %A, %B, and the returned vector all have the same float or +integer element type. '``llvm.matrix.column.major.load.*``' Intrinsic @@ -15609,6 +15617,7 @@ must have * elements and the returned vector must have Syntax: """"""" +This is an overloaded intrinsic. :: @@ -15618,22 +15627,26 @@ Syntax: Overview: """"""""" -The '``llvm.matrix.column.major.load.*``' intrinsic loads a matrix with -rows and columns, using a stride of %Stride between columns. For two -consecutive columns A and B, %Stride refers to the distance (the number of -elements) between the start of column A and the start of column B. The result -matrix is returned embedded in the result vector. This allows for convenient -loading of sub matrixes. If is true, the intrinsic is considered -a :ref:`volatile memory access `. - -If the %Ptr argument is known to be aligned to some boundary, this can be -specified as an attribute on the argument. +The '``llvm.matrix.column.major.load.*``' intrinsics load a x +matrix using a stride of %Stride to compute the start address of the different +columns. This allows for convenient loading of sub matrixes. If +is true, the intrinsic is considered a :ref:`volatile memory access +`. The result matrix is returned in the result vector. If the %Ptr +argument is known to be aligned to some boundary, this can be specified as an +attribute on the argument. Arguments: """""""""" -The , and arguments must be constant integers. The -returned vector must have * elements. %Stride must be >= . +The first argument %Ptr is a pointer type to the returned vector type, and +correponds to the start address to load from. The second argument %Stride is a +postive, constant integer with %Stride ``>=`` . %Stride is used to compute +the column memory addresses. I.e., for a column ``C``, its start memory +addresses is calculated with %Ptr + ``C`` * %Stride. The third Argument + is a boolean value. The fourth and fifth arguments, and +, correspond to the number of rows and columns, respectively, and must be +positive, constant integers. The returned vector must have * +elements. The :ref:`align ` parameter attribute can be provided for the %Ptr arguments. @@ -15653,12 +15666,10 @@ Syntax: Overview: """"""""" -The '``llvm.matrix.column.major.store.*``' intrinsic stores the matrix with - rows and columns embedded in %In, using a stride of %Stride -between columns. For two consecutive columns A and B, %Stride refers to the -distance (the number of elements) between the start of column A and the start -of column B. If is true, the intrinsic is considered a -:ref:`volatile memory access `. +The '``llvm.matrix.column.major.store.*``' intrinsics store the x +matrix in %In to memory using a stride of %Stride between columns. If + is true, the intrinsic is considered a :ref:`volatile memory +access `. If the %Ptr argument is known to be aligned to some boundary, this can be specified as an attribute on the argument. @@ -15666,8 +15677,15 @@ specified as an attribute on the argument. Arguments: """""""""" -The , , arguments must be constant integers. The -vector argument %In must have * elements. %Stride must be >= . +The first argument %In is a vector that corresponds to a x matrix +to be stored to memory. The second argument %Ptr is a pointer to the vector +type of %In, and is the start address of the matrix in memory. The third +argument %Stride is a positive, constant integer with %Stride ``>=`` . +%Stride is used to compute the column memory addresses. I.e., for a column +``C``, its start memory addresses is calculated with %Ptr + ``C`` * %Stride. +The fourth argument is a boolean value. The arguments and + correspond to the number of rows and columns, respectively, and must be +positive, constant integers. The :ref:`align ` parameter attribute can be provided for the %Ptr arguments. diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 8fa87b7489013..994082fbdb7c1 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5006,36 +5006,77 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { case Intrinsic::matrix_transpose: case Intrinsic::matrix_column_major_load: case Intrinsic::matrix_column_major_store: { + Function *IF = Call.getCalledFunction(); + ConstantInt *Stride = nullptr; ConstantInt *NumRows; ConstantInt *NumColumns; - VectorType *TypeToCheck; + VectorType *ResultTy; + Type *Op0ElemTy = nullptr; + Type *Op1ElemTy = nullptr; switch (ID) { case Intrinsic::matrix_multiply: NumRows = cast(Call.getArgOperand(2)); NumColumns = cast(Call.getArgOperand(4)); - TypeToCheck = cast(Call.getType()); + ResultTy = cast(Call.getType()); + Op0ElemTy = + cast(Call.getArgOperand(0)->getType())->getElementType(); + Op1ElemTy = + cast(Call.getArgOperand(1)->getType())->getElementType(); break; case Intrinsic::matrix_transpose: NumRows = cast(Call.getArgOperand(1)); NumColumns = cast(Call.getArgOperand(2)); - TypeToCheck = cast(Call.getType()); + ResultTy = cast(Call.getType()); + Op0ElemTy = + cast(Call.getArgOperand(0)->getType())->getElementType(); break; - case Intrinsic::matrix_column_major_load: + case Intrinsic::matrix_column_major_load: { + Stride = dyn_cast(Call.getArgOperand(1)); NumRows = cast(Call.getArgOperand(3)); NumColumns = cast(Call.getArgOperand(4)); - TypeToCheck = cast(Call.getType()); + ResultTy = cast(Call.getType()); + auto *VecTy = cast( + cast(Call.getArgOperand(0)->getType())->getElementType()); + Op0ElemTy = VecTy->getElementType(); + } break; - case Intrinsic::matrix_column_major_store: + case Intrinsic::matrix_column_major_store: { + Stride = dyn_cast(Call.getArgOperand(2)); NumRows = cast(Call.getArgOperand(4)); NumColumns = cast(Call.getArgOperand(5)); - TypeToCheck = cast(Call.getArgOperand(0)->getType()); + ResultTy = cast(Call.getArgOperand(0)->getType()); + Op0ElemTy = + cast(Call.getArgOperand(0)->getType())->getElementType(); + auto *VecTy = cast( + cast(Call.getArgOperand(1)->getType())->getElementType()); + Op1ElemTy = VecTy->getElementType(); + } break; default: llvm_unreachable("unexpected intrinsic"); } - Assert(TypeToCheck->getNumElements() == + + Assert(ResultTy->getElementType()->isIntegerTy() || + ResultTy->getElementType()->isFloatingPointTy(), + "Result type must be an integer or floating-point type!", IF); + + Assert(ResultTy->getElementType() == Op0ElemTy, + "Vector element type mismatch of the result and first operand " + "vector!", IF); + + if (Op1ElemTy) + Assert(ResultTy->getElementType() == Op1ElemTy, + "Vector element type mismatch of the result and second operand " + "vector!", IF); + + Assert(ResultTy->getNumElements() == NumRows->getZExtValue() * NumColumns->getZExtValue(), - "result of a matrix operation does not fit in the returned vector"); + "Result of a matrix operation does not fit in the returned vector!"); + + if (Stride) + Assert(Stride->getZExtValue() >= NumRows->getZExtValue(), + "Stride must be greater or equal than the number of rows!", IF); + break; } }; diff --git a/llvm/test/Verifier/matrix-intrinsics.ll b/llvm/test/Verifier/matrix-intrinsics.ll index 6b2a4c501c660..5afab26a48c53 100644 --- a/llvm/test/Verifier/matrix-intrinsics.ll +++ b/llvm/test/Verifier/matrix-intrinsics.ll @@ -3,9 +3,9 @@ declare <4 x float> @llvm.matrix.transpose.v4f32(<4 x float>, i32, i32) define <4 x float> @transpose(<4 x float> %m, i32 %arg) { ; CHECK: assembly parsed, but does not verify as correct! -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! ; CHECK-NEXT: immarg operand has non-immediate parameter ; CHECK-NEXT: i32 %arg ; CHECK-NEXT: %result.3 = call <4 x float> @llvm.matrix.transpose.v4f32(<4 x float> %result.2, i32 %arg, i32 2) @@ -22,9 +22,9 @@ define <4 x float> @transpose(<4 x float> %m, i32 %arg) { declare <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4f32(<4 x float>, <4 x float>, i32, i32, i32) define <4 x float> @multiply(<4 x float> %m, i32 %arg) { -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! ; CHECK-NEXT: immarg operand has non-immediate parameter ; CHECK-NEXT: i32 %arg ; CHECK-NEXT: %result.3 = call <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4f32(<4 x float> %result.2, <4 x float> %m, i32 %arg, i32 2, i32 1) @@ -38,9 +38,9 @@ define <4 x float> @multiply(<4 x float> %m, i32 %arg) { declare <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4f32(<4 x float>*, i64, i1, i32, i32) declare <6 x float> @llvm.matrix.column.major.load.v6f32.p0v6f32(<6 x float>*, i64, i1, i32, i32) define <4 x float> @column.major_load(<4 x float>* %m, <6 x float>* %n, i32 %arg) { -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! ; CHECK-NEXT: immarg operand has non-immediate parameter ; CHECK-NEXT: i32 %arg ; CHECK-NEXT: %result.3 = call <6 x float> @llvm.matrix.column.major.load.v6f32.p0v6f32(<6 x float>* %n, i64 2, i1 true, i32 3, i32 %arg) @@ -54,13 +54,110 @@ define <4 x float> @column.major_load(<4 x float>* %m, <6 x float>* %n, i32 %arg declare void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float>, <4 x float>*, i64, i1, i32, i32) declare void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float>, <6 x float>*, i64, i1, i32, i32) define void @column.major_store(<4 x float>* %m, <6 x float>* %n, i64 %arg) { -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector -; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 0, i1 false, i32 0, i32 0) call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 2, i1 false, i32 1, i32 2) call void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float> zeroinitializer, <6 x float>* %n, i64 2, i1 false, i32 3, i32 3) call void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float> zeroinitializer, <6 x float>* %n, i64 %arg, i1 false, i32 3, i32 3) ret void } + +declare <4 x float> @llvm.matrix.transpose.v4f32.v4i32(<4 x i32>, i32, i32) +declare <4 x i32> @llvm.matrix.transpose.v4i32.v4f32(<4 x float>, i32, i32) + +define <4 x float> @transpose_mixed_types(<4 x float> %fvec, <4 x i32> %ivec, i32 %arg) { +; +; CHECK-NEXT: Intrinsic has incorrect argument type! +; CHECK-NEXT: <4 x float> (<4 x i32>, i32, i32)* @llvm.matrix.transpose.v4f32.v4i32 +; CHECK-NEXT: Intrinsic has incorrect argument type! +; CHECK-NEXT: <4 x i32> (<4 x float>, i32, i32)* @llvm.matrix.transpose.v4i32.v4f32 +; + %result.0 = call <4 x float> @llvm.matrix.transpose.v4f32.v4i32(<4 x i32> %ivec, i32 0, i32 0) + %result.1 = call <4 x i32> @llvm.matrix.transpose.v4i32.v4f32(<4 x float> %result.0, i32 3, i32 2) + ret <4 x float> %result.0 +} + +declare <4 x i32> @llvm.matrix.multiply.v4i32.v4f32.v4f32(<4 x float>, <4 x float>, i32, i32, i32) +declare <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4f32(<4 x i32>, <4 x float>, i32, i32, i32) +declare <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4i32(<4 x float>, <4 x i32>, i32, i32, i32) +declare <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4i32(<4 x i32>, <4 x i32>, i32, i32, i32) + +define <4 x float> @multiply_mixed_types(<4 x i32> %ivec, <4 x float> %fvec, i32 %arg) { +; +; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! +; CHECK-NEXT: <4 x i32> (<4 x float>, <4 x float>, i32, i32, i32)* @llvm.matrix.multiply.v4i32.v4f32.v4f32 +; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! +; CHECK-NEXT: <4 x float> (<4 x i32>, <4 x float>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4i32.v4f32 +; CHECK-NEXT: Vector element type mismatch of the result and second operand vector! +; CHECK-NEXT: <4 x float> (<4 x float>, <4 x i32>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4f32.v4i32 +; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! +; CHECK-NEXT: <4 x float> (<4 x i32>, <4 x i32>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4i32.v4i32 +; + %result.0 = call <4 x i32> @llvm.matrix.multiply.v4i32.v4f32.v4f32(<4 x float> %fvec, <4 x float> %fvec, i32 2, i32 2, i32 2) + %result.1 = call <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4f32(<4 x i32> %result.0, <4 x float> %fvec, i32 2, i32 2, i32 2) + %result.2 = call <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4i32(<4 x float> %fvec, <4 x i32> %ivec, i32 2, i32 2, i32 2) + %result.3 = call <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4i32(<4 x i32> %ivec, <4 x i32> %ivec, i32 2, i32 2, i32 2) + ret <4 x float> %result.3 +} + +declare <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4i32(<4 x i32>*, i64, i1, i32, i32) +declare <4 x i32> @llvm.matrix.column.major.load.v4i32.p0v4f32(<4 x float>*, i64, i1, i32, i32) + +define <4 x float> @column.major_load_mixed_types(<4 x i32>* %m, <4 x float>* %n, i32 %arg) { +; +; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! +; CHECK-NEXT: <4 x float> (<4 x i32>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32.p0v4i32 +; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! +; CHECK-NEXT: <4 x i32> (<4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4i32.p0v4f32 +; + %result.0 = call <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4i32(<4 x i32>* %m, i64 2, i1 false, i32 2, i32 2) + %result.1 = call <4 x i32> @llvm.matrix.column.major.load.v4i32.p0v4f32(<4 x float>* %n, i64 2, i1 false, i32 2, i32 2) + ret <4 x float> %result.0 +} + +declare void @llvm.matrix.column.major.store.v4i32.p0v4f32(<4 x i32>, <4 x float>*, i64, i1, i32, i32) +declare void @llvm.matrix.column.major.store.v4f32.p0v4i32(<4 x float>, <4 x i32>*, i64, i1, i32, i32) + +define void @column.major_store_mixed_types(<4 x float>* %m, <4 x i32>* %n, i64 %arg) { +; +; CHECK-NEXT: Vector element type mismatch of the result and second operand vector! +; CHECK-NEXT: void (<4 x i32>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4i32.p0v4f32 +; CHECK-NEXT: Vector element type mismatch of the result and second operand vector! +; CHECK-NEXT: void (<4 x float>, <4 x i32>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32.p0v4i32 +; + call void @llvm.matrix.column.major.store.v4i32.p0v4f32(<4 x i32> zeroinitializer, <4 x float>* %m, i64 2, i1 false, i32 2, i32 2) + call void @llvm.matrix.column.major.store.v4f32.p0v4i32(<4 x float> zeroinitializer, <4 x i32>* %n, i64 2, i1 false, i32 2, i32 2) + ret void +} + +declare void @llvm.matrix.column.major.store.v4f32p0.p0v4f32(<4 x float*>, <4 x float>*, i64, i1, i32, i32) + +define void @column.major_store_non_int_float_type(<4 x float>* %m, <4 x float>* %n, i64 %arg) { +; +; CHECK-NEXT: Result type must be an integer or floating-point type! +; CHECK-NEXT: void (<4 x float*>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4p0f32.p0v4f32 +; + call void @llvm.matrix.column.major.store.v4f32p0.p0v4f32(<4 x float*> zeroinitializer, <4 x float>* %n, i64 2, i1 false, i32 2, i32 2) + ret void +} + +define <4 x float> @column.major_load_stride_too_small(<4 x float>* %m, i32 %arg) { +; +; CHECK-NEXT: Stride must be greater or equal than the number of rows! +; CHECK-NEXT: <4 x float> (<4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32.p0v4f32 +; + %result.1 = call <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4f32(<4 x float>* %m, i64 1, i1 false, i32 2, i32 2) + ret <4 x float> %result.1 +} + +define void @column.major_store_stride_too_small(<4 x float>* %m, i64 %arg) { +; +; CHECK-NEXT: Stride must be greater or equal than the number of rows! +; CHECK-NEXT: void (<4 x float>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32.p0v4f32 +; + call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 1, i1 false, i32 2, i32 2) + ret void +} From 4ff7ed33108d9039fd960a4979b2e1503888582c Mon Sep 17 00:00:00 2001 From: Sjoerd Meijer Date: Sun, 12 Jul 2020 19:19:25 +0100 Subject: [PATCH 051/771] Revert "[Matrix] Tighten LangRef definitions and Verifier checks." This reverts commit f4d29d6e8c43cfd924d9d7cc1ac0c269b2788e75. Hm, some build bot failures, reverting it while I investigate that. --- llvm/docs/LangRef.rst | 96 ++++++++---------- llvm/lib/IR/Verifier.cpp | 59 ++---------- llvm/test/Verifier/matrix-intrinsics.ll | 123 +++--------------------- 3 files changed, 61 insertions(+), 217 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 02c92f1a4daa6..86d315be74bcf 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -15524,7 +15524,6 @@ The argument to this intrinsic must be a vector of floating-point values. Syntax: """"""" -This is an overloaded intrinsic. :: @@ -15549,20 +15548,17 @@ Matrix Intrinsics ----------------- Operations on matrixes requiring shape information (like number of rows/columns -or the memory layout) can be expressed using the matrix intrinsics. These -intrinsics require matrix dimensions to be passed as immediate arguments, and -matrixes are passed and returned as vectors. This means that for a ``R`` x -``C`` matrix, element ``i`` of column ``j`` is at index ``j * R + i`` in the -corresponding vector, with indices starting at 0. Currently column-major layout -is assumed. The intrinsics support both integer and floating point matrixes. +or the memory layout) can be expressed using the matrix intrinsics. Matrixes are +embedded in a flat vector and the intrinsics take the dimensions as arguments. +Currently column-major layout is assumed. The intrinsics support both integer +and floating point matrixes. '``llvm.matrix.transpose.*``' Intrinsic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: """"""" -This is an overloaded intrinsic. :: @@ -15571,24 +15567,21 @@ This is an overloaded intrinsic. Overview: """"""""" -The '``llvm.matrix.transpose.*``' intrinsics treat %In as a x matrix -and return the transposed matrix in the result vector. +The '``llvm.matrix.transpose.*``' intrinsic treats %In as containing a matrix +with rows and columns and returns the transposed matrix embedded in +the result vector. Arguments: """""""""" -First argument %In is vector that corresponds to a x matrix. -Thus, arguments and correspond to the number of rows and columns, -respectively, and must be positive, constant integers. The returned vector must -have * elements, and have the same float or integer element type -as %In. +The and arguments must be constant integers. The vector argument +%In and the returned vector must have * elements. '``llvm.matrix.multiply.*``' Intrinsic -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Syntax: """"""" -This is an overloaded intrinsic. :: @@ -15597,19 +15590,18 @@ This is an overloaded intrinsic. Overview: """"""""" -The '``llvm.matrix.multiply.*``' intrinsics treat %A as a x -matrix, %B as a x matrix, and multiplies them. The result -matrix is returned in the result vector. +The '``llvm.matrix.multiply.*``' intrinsic treats %A as a matrix with +rows and columns, %B as a matrix with rows and +columns and multiplies them. The result matrix is returned embedded in the +result vector. Arguments: """""""""" -The first vector argument %A corresponds to a matrix with * -elements, and the second argument %B to a matrix with * -elements. Arguments , and must be positive, -constant integers. The returned vector must have * -elements. Vectors %A, %B, and the returned vector all have the same float or -integer element type. +The , and arguments must be constant +integers. The vector argument %A must have * elements, %B +must have * elements and the returned vector must have + * elements. '``llvm.matrix.column.major.load.*``' Intrinsic @@ -15617,7 +15609,6 @@ integer element type. Syntax: """"""" -This is an overloaded intrinsic. :: @@ -15627,26 +15618,22 @@ This is an overloaded intrinsic. Overview: """"""""" -The '``llvm.matrix.column.major.load.*``' intrinsics load a x -matrix using a stride of %Stride to compute the start address of the different -columns. This allows for convenient loading of sub matrixes. If -is true, the intrinsic is considered a :ref:`volatile memory access -`. The result matrix is returned in the result vector. If the %Ptr -argument is known to be aligned to some boundary, this can be specified as an -attribute on the argument. +The '``llvm.matrix.column.major.load.*``' intrinsic loads a matrix with +rows and columns, using a stride of %Stride between columns. For two +consecutive columns A and B, %Stride refers to the distance (the number of +elements) between the start of column A and the start of column B. The result +matrix is returned embedded in the result vector. This allows for convenient +loading of sub matrixes. If is true, the intrinsic is considered +a :ref:`volatile memory access `. + +If the %Ptr argument is known to be aligned to some boundary, this can be +specified as an attribute on the argument. Arguments: """""""""" -The first argument %Ptr is a pointer type to the returned vector type, and -correponds to the start address to load from. The second argument %Stride is a -postive, constant integer with %Stride ``>=`` . %Stride is used to compute -the column memory addresses. I.e., for a column ``C``, its start memory -addresses is calculated with %Ptr + ``C`` * %Stride. The third Argument - is a boolean value. The fourth and fifth arguments, and -, correspond to the number of rows and columns, respectively, and must be -positive, constant integers. The returned vector must have * -elements. +The , and arguments must be constant integers. The +returned vector must have * elements. %Stride must be >= . The :ref:`align ` parameter attribute can be provided for the %Ptr arguments. @@ -15666,10 +15653,12 @@ Syntax: Overview: """"""""" -The '``llvm.matrix.column.major.store.*``' intrinsics store the x -matrix in %In to memory using a stride of %Stride between columns. If - is true, the intrinsic is considered a :ref:`volatile memory -access `. +The '``llvm.matrix.column.major.store.*``' intrinsic stores the matrix with + rows and columns embedded in %In, using a stride of %Stride +between columns. For two consecutive columns A and B, %Stride refers to the +distance (the number of elements) between the start of column A and the start +of column B. If is true, the intrinsic is considered a +:ref:`volatile memory access `. If the %Ptr argument is known to be aligned to some boundary, this can be specified as an attribute on the argument. @@ -15677,15 +15666,8 @@ specified as an attribute on the argument. Arguments: """""""""" -The first argument %In is a vector that corresponds to a x matrix -to be stored to memory. The second argument %Ptr is a pointer to the vector -type of %In, and is the start address of the matrix in memory. The third -argument %Stride is a positive, constant integer with %Stride ``>=`` . -%Stride is used to compute the column memory addresses. I.e., for a column -``C``, its start memory addresses is calculated with %Ptr + ``C`` * %Stride. -The fourth argument is a boolean value. The arguments and - correspond to the number of rows and columns, respectively, and must be -positive, constant integers. +The , , arguments must be constant integers. The +vector argument %In must have * elements. %Stride must be >= . The :ref:`align ` parameter attribute can be provided for the %Ptr arguments. diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 994082fbdb7c1..8fa87b7489013 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5006,77 +5006,36 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { case Intrinsic::matrix_transpose: case Intrinsic::matrix_column_major_load: case Intrinsic::matrix_column_major_store: { - Function *IF = Call.getCalledFunction(); - ConstantInt *Stride = nullptr; ConstantInt *NumRows; ConstantInt *NumColumns; - VectorType *ResultTy; - Type *Op0ElemTy = nullptr; - Type *Op1ElemTy = nullptr; + VectorType *TypeToCheck; switch (ID) { case Intrinsic::matrix_multiply: NumRows = cast(Call.getArgOperand(2)); NumColumns = cast(Call.getArgOperand(4)); - ResultTy = cast(Call.getType()); - Op0ElemTy = - cast(Call.getArgOperand(0)->getType())->getElementType(); - Op1ElemTy = - cast(Call.getArgOperand(1)->getType())->getElementType(); + TypeToCheck = cast(Call.getType()); break; case Intrinsic::matrix_transpose: NumRows = cast(Call.getArgOperand(1)); NumColumns = cast(Call.getArgOperand(2)); - ResultTy = cast(Call.getType()); - Op0ElemTy = - cast(Call.getArgOperand(0)->getType())->getElementType(); + TypeToCheck = cast(Call.getType()); break; - case Intrinsic::matrix_column_major_load: { - Stride = dyn_cast(Call.getArgOperand(1)); + case Intrinsic::matrix_column_major_load: NumRows = cast(Call.getArgOperand(3)); NumColumns = cast(Call.getArgOperand(4)); - ResultTy = cast(Call.getType()); - auto *VecTy = cast( - cast(Call.getArgOperand(0)->getType())->getElementType()); - Op0ElemTy = VecTy->getElementType(); - } + TypeToCheck = cast(Call.getType()); break; - case Intrinsic::matrix_column_major_store: { - Stride = dyn_cast(Call.getArgOperand(2)); + case Intrinsic::matrix_column_major_store: NumRows = cast(Call.getArgOperand(4)); NumColumns = cast(Call.getArgOperand(5)); - ResultTy = cast(Call.getArgOperand(0)->getType()); - Op0ElemTy = - cast(Call.getArgOperand(0)->getType())->getElementType(); - auto *VecTy = cast( - cast(Call.getArgOperand(1)->getType())->getElementType()); - Op1ElemTy = VecTy->getElementType(); - } + TypeToCheck = cast(Call.getArgOperand(0)->getType()); break; default: llvm_unreachable("unexpected intrinsic"); } - - Assert(ResultTy->getElementType()->isIntegerTy() || - ResultTy->getElementType()->isFloatingPointTy(), - "Result type must be an integer or floating-point type!", IF); - - Assert(ResultTy->getElementType() == Op0ElemTy, - "Vector element type mismatch of the result and first operand " - "vector!", IF); - - if (Op1ElemTy) - Assert(ResultTy->getElementType() == Op1ElemTy, - "Vector element type mismatch of the result and second operand " - "vector!", IF); - - Assert(ResultTy->getNumElements() == + Assert(TypeToCheck->getNumElements() == NumRows->getZExtValue() * NumColumns->getZExtValue(), - "Result of a matrix operation does not fit in the returned vector!"); - - if (Stride) - Assert(Stride->getZExtValue() >= NumRows->getZExtValue(), - "Stride must be greater or equal than the number of rows!", IF); - + "result of a matrix operation does not fit in the returned vector"); break; } }; diff --git a/llvm/test/Verifier/matrix-intrinsics.ll b/llvm/test/Verifier/matrix-intrinsics.ll index 5afab26a48c53..6b2a4c501c660 100644 --- a/llvm/test/Verifier/matrix-intrinsics.ll +++ b/llvm/test/Verifier/matrix-intrinsics.ll @@ -3,9 +3,9 @@ declare <4 x float> @llvm.matrix.transpose.v4f32(<4 x float>, i32, i32) define <4 x float> @transpose(<4 x float> %m, i32 %arg) { ; CHECK: assembly parsed, but does not verify as correct! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector ; CHECK-NEXT: immarg operand has non-immediate parameter ; CHECK-NEXT: i32 %arg ; CHECK-NEXT: %result.3 = call <4 x float> @llvm.matrix.transpose.v4f32(<4 x float> %result.2, i32 %arg, i32 2) @@ -22,9 +22,9 @@ define <4 x float> @transpose(<4 x float> %m, i32 %arg) { declare <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4f32(<4 x float>, <4 x float>, i32, i32, i32) define <4 x float> @multiply(<4 x float> %m, i32 %arg) { -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector ; CHECK-NEXT: immarg operand has non-immediate parameter ; CHECK-NEXT: i32 %arg ; CHECK-NEXT: %result.3 = call <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4f32(<4 x float> %result.2, <4 x float> %m, i32 %arg, i32 2, i32 1) @@ -38,9 +38,9 @@ define <4 x float> @multiply(<4 x float> %m, i32 %arg) { declare <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4f32(<4 x float>*, i64, i1, i32, i32) declare <6 x float> @llvm.matrix.column.major.load.v6f32.p0v6f32(<6 x float>*, i64, i1, i32, i32) define <4 x float> @column.major_load(<4 x float>* %m, <6 x float>* %n, i32 %arg) { -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector ; CHECK-NEXT: immarg operand has non-immediate parameter ; CHECK-NEXT: i32 %arg ; CHECK-NEXT: %result.3 = call <6 x float> @llvm.matrix.column.major.load.v6f32.p0v6f32(<6 x float>* %n, i64 2, i1 true, i32 3, i32 %arg) @@ -54,110 +54,13 @@ define <4 x float> @column.major_load(<4 x float>* %m, <6 x float>* %n, i32 %arg declare void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float>, <4 x float>*, i64, i1, i32, i32) declare void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float>, <6 x float>*, i64, i1, i32, i32) define void @column.major_store(<4 x float>* %m, <6 x float>* %n, i64 %arg) { -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! -; CHECK-NEXT: Result of a matrix operation does not fit in the returned vector! +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector +; CHECK-NEXT: result of a matrix operation does not fit in the returned vector call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 0, i1 false, i32 0, i32 0) call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 2, i1 false, i32 1, i32 2) call void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float> zeroinitializer, <6 x float>* %n, i64 2, i1 false, i32 3, i32 3) call void @llvm.matrix.column.major.store.v6f32.p0v6f32(<6 x float> zeroinitializer, <6 x float>* %n, i64 %arg, i1 false, i32 3, i32 3) ret void } - -declare <4 x float> @llvm.matrix.transpose.v4f32.v4i32(<4 x i32>, i32, i32) -declare <4 x i32> @llvm.matrix.transpose.v4i32.v4f32(<4 x float>, i32, i32) - -define <4 x float> @transpose_mixed_types(<4 x float> %fvec, <4 x i32> %ivec, i32 %arg) { -; -; CHECK-NEXT: Intrinsic has incorrect argument type! -; CHECK-NEXT: <4 x float> (<4 x i32>, i32, i32)* @llvm.matrix.transpose.v4f32.v4i32 -; CHECK-NEXT: Intrinsic has incorrect argument type! -; CHECK-NEXT: <4 x i32> (<4 x float>, i32, i32)* @llvm.matrix.transpose.v4i32.v4f32 -; - %result.0 = call <4 x float> @llvm.matrix.transpose.v4f32.v4i32(<4 x i32> %ivec, i32 0, i32 0) - %result.1 = call <4 x i32> @llvm.matrix.transpose.v4i32.v4f32(<4 x float> %result.0, i32 3, i32 2) - ret <4 x float> %result.0 -} - -declare <4 x i32> @llvm.matrix.multiply.v4i32.v4f32.v4f32(<4 x float>, <4 x float>, i32, i32, i32) -declare <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4f32(<4 x i32>, <4 x float>, i32, i32, i32) -declare <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4i32(<4 x float>, <4 x i32>, i32, i32, i32) -declare <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4i32(<4 x i32>, <4 x i32>, i32, i32, i32) - -define <4 x float> @multiply_mixed_types(<4 x i32> %ivec, <4 x float> %fvec, i32 %arg) { -; -; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! -; CHECK-NEXT: <4 x i32> (<4 x float>, <4 x float>, i32, i32, i32)* @llvm.matrix.multiply.v4i32.v4f32.v4f32 -; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! -; CHECK-NEXT: <4 x float> (<4 x i32>, <4 x float>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4i32.v4f32 -; CHECK-NEXT: Vector element type mismatch of the result and second operand vector! -; CHECK-NEXT: <4 x float> (<4 x float>, <4 x i32>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4f32.v4i32 -; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! -; CHECK-NEXT: <4 x float> (<4 x i32>, <4 x i32>, i32, i32, i32)* @llvm.matrix.multiply.v4f32.v4i32.v4i32 -; - %result.0 = call <4 x i32> @llvm.matrix.multiply.v4i32.v4f32.v4f32(<4 x float> %fvec, <4 x float> %fvec, i32 2, i32 2, i32 2) - %result.1 = call <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4f32(<4 x i32> %result.0, <4 x float> %fvec, i32 2, i32 2, i32 2) - %result.2 = call <4 x float> @llvm.matrix.multiply.v4f32.v4f32.v4i32(<4 x float> %fvec, <4 x i32> %ivec, i32 2, i32 2, i32 2) - %result.3 = call <4 x float> @llvm.matrix.multiply.v4f32.v4i32.v4i32(<4 x i32> %ivec, <4 x i32> %ivec, i32 2, i32 2, i32 2) - ret <4 x float> %result.3 -} - -declare <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4i32(<4 x i32>*, i64, i1, i32, i32) -declare <4 x i32> @llvm.matrix.column.major.load.v4i32.p0v4f32(<4 x float>*, i64, i1, i32, i32) - -define <4 x float> @column.major_load_mixed_types(<4 x i32>* %m, <4 x float>* %n, i32 %arg) { -; -; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! -; CHECK-NEXT: <4 x float> (<4 x i32>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32.p0v4i32 -; CHECK-NEXT: Vector element type mismatch of the result and first operand vector! -; CHECK-NEXT: <4 x i32> (<4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4i32.p0v4f32 -; - %result.0 = call <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4i32(<4 x i32>* %m, i64 2, i1 false, i32 2, i32 2) - %result.1 = call <4 x i32> @llvm.matrix.column.major.load.v4i32.p0v4f32(<4 x float>* %n, i64 2, i1 false, i32 2, i32 2) - ret <4 x float> %result.0 -} - -declare void @llvm.matrix.column.major.store.v4i32.p0v4f32(<4 x i32>, <4 x float>*, i64, i1, i32, i32) -declare void @llvm.matrix.column.major.store.v4f32.p0v4i32(<4 x float>, <4 x i32>*, i64, i1, i32, i32) - -define void @column.major_store_mixed_types(<4 x float>* %m, <4 x i32>* %n, i64 %arg) { -; -; CHECK-NEXT: Vector element type mismatch of the result and second operand vector! -; CHECK-NEXT: void (<4 x i32>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4i32.p0v4f32 -; CHECK-NEXT: Vector element type mismatch of the result and second operand vector! -; CHECK-NEXT: void (<4 x float>, <4 x i32>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32.p0v4i32 -; - call void @llvm.matrix.column.major.store.v4i32.p0v4f32(<4 x i32> zeroinitializer, <4 x float>* %m, i64 2, i1 false, i32 2, i32 2) - call void @llvm.matrix.column.major.store.v4f32.p0v4i32(<4 x float> zeroinitializer, <4 x i32>* %n, i64 2, i1 false, i32 2, i32 2) - ret void -} - -declare void @llvm.matrix.column.major.store.v4f32p0.p0v4f32(<4 x float*>, <4 x float>*, i64, i1, i32, i32) - -define void @column.major_store_non_int_float_type(<4 x float>* %m, <4 x float>* %n, i64 %arg) { -; -; CHECK-NEXT: Result type must be an integer or floating-point type! -; CHECK-NEXT: void (<4 x float*>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4p0f32.p0v4f32 -; - call void @llvm.matrix.column.major.store.v4f32p0.p0v4f32(<4 x float*> zeroinitializer, <4 x float>* %n, i64 2, i1 false, i32 2, i32 2) - ret void -} - -define <4 x float> @column.major_load_stride_too_small(<4 x float>* %m, i32 %arg) { -; -; CHECK-NEXT: Stride must be greater or equal than the number of rows! -; CHECK-NEXT: <4 x float> (<4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.load.v4f32.p0v4f32 -; - %result.1 = call <4 x float> @llvm.matrix.column.major.load.v4f32.p0v4f32(<4 x float>* %m, i64 1, i1 false, i32 2, i32 2) - ret <4 x float> %result.1 -} - -define void @column.major_store_stride_too_small(<4 x float>* %m, i64 %arg) { -; -; CHECK-NEXT: Stride must be greater or equal than the number of rows! -; CHECK-NEXT: void (<4 x float>, <4 x float>*, i64, i1, i32, i32)* @llvm.matrix.column.major.store.v4f32.p0v4f32 -; - call void @llvm.matrix.column.major.store.v4f32.p0v4f32(<4 x float> zeroinitializer, <4 x float>* %m, i64 1, i1 false, i32 2, i32 2) - ret void -} From 445897334741c53e98f8044f5f33ab1e888b3818 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 12 Jul 2020 15:56:26 -0400 Subject: [PATCH 052/771] [InstCombine] fold mul of zext/sext bools to 'and' Similar to rG40fcc42: The base case only worked because we were relying on a poison-unsafe select transform; if that is fixed, we would regress on patterns like this. The extra use tests show that the select transform can't be applied consistently. So it may be a regression to have an extra instruction on 1 test, but that result was not created safely and does not happen reliably. --- .../Transforms/InstCombine/InstCombineMulDivRem.cpp | 10 ++++++++++ llvm/test/Transforms/InstCombine/mul.ll | 11 ++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 2965103d40295..c6233a68847dd 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -376,6 +376,16 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { Value *And = Builder.CreateAnd(X, Y, "mulbool"); return CastInst::Create(Instruction::ZExt, And, I.getType()); } + // (sext bool X) * (zext bool Y) --> sext (and X, Y) + // (zext bool X) * (sext bool Y) --> sext (and X, Y) + // Note: -1 * 1 == 1 * -1 == -1 + if (((match(Op0, m_SExt(m_Value(X))) && match(Op1, m_ZExt(m_Value(Y)))) || + (match(Op0, m_ZExt(m_Value(X))) && match(Op1, m_SExt(m_Value(Y))))) && + X->getType()->isIntOrIntVectorTy(1) && X->getType() == Y->getType() && + (Op0->hasOneUse() || Op1->hasOneUse())) { + Value *And = Builder.CreateAnd(X, Y, "mulbool"); + return CastInst::Create(Instruction::SExt, And, I.getType()); + } // (bool X) * Y --> X ? Y : 0 // Y * (bool X) --> X ? Y : 0 diff --git a/llvm/test/Transforms/InstCombine/mul.ll b/llvm/test/Transforms/InstCombine/mul.ll index 9d1b8ad457e41..059b18d30b907 100644 --- a/llvm/test/Transforms/InstCombine/mul.ll +++ b/llvm/test/Transforms/InstCombine/mul.ll @@ -247,8 +247,8 @@ define i32 @mul_bools_sext_use3(i1 %x, i1 %y) { define <3 x i32> @mul_bools_mixed_ext(<3 x i1> %x, <3 x i1> %y) { ; CHECK-LABEL: @mul_bools_mixed_ext( -; CHECK-NEXT: [[NARROW:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[NARROW]] to <3 x i32> +; CHECK-NEXT: [[MULBOOL:%.*]] = and <3 x i1> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = sext <3 x i1> [[MULBOOL]] to <3 x i32> ; CHECK-NEXT: ret <3 x i32> [[R]] ; %zx = zext <3 x i1> %x to <3 x i32> @@ -261,8 +261,8 @@ define i32 @mul_bools_mixed_ext_use1(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_mixed_ext_use1( ; CHECK-NEXT: [[ZY:%.*]] = zext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[ZY]]) -; CHECK-NEXT: [[NARROW:%.*]] = and i1 [[Y]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = sext i1 [[NARROW]] to i32 +; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[X:%.*]], [[Y]] +; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %sx = sext i1 %x to i32 @@ -276,7 +276,8 @@ define i32 @mul_bools_mixed_ext_use2(i1 %x, i1 %y) { ; CHECK-LABEL: @mul_bools_mixed_ext_use2( ; CHECK-NEXT: [[SY:%.*]] = sext i1 [[Y:%.*]] to i32 ; CHECK-NEXT: call void @use32(i32 [[SY]]) -; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i32 [[SY]], i32 0 +; CHECK-NEXT: [[MULBOOL:%.*]] = and i1 [[Y]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = sext i1 [[MULBOOL]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %zx = zext i1 %x to i32 From b92c2bb6a2058611d727c4e2ce3a928f0a3e647d Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 12 Jul 2020 12:58:10 -0700 Subject: [PATCH 053/771] [X86] Add CPU name strings to getIntelProcessorTypeAndSubtype and getAMDProcessorTypeAndSubtype in compiler-rt. These aren't used in compiler-rt, but I plan to make a similar change to the equivalent code in Host.cpp where the mapping from type/subtype is an unnecessary complication. Having the CPU strings here will help keep the code somewhat synchronized. --- compiler-rt/lib/builtins/cpu_model.c | 125 ++++++++++++++++++--------- 1 file changed, 85 insertions(+), 40 deletions(-) diff --git a/compiler-rt/lib/builtins/cpu_model.c b/compiler-rt/lib/builtins/cpu_model.c index 042657232d8e8..8346bb62dcfb4 100644 --- a/compiler-rt/lib/builtins/cpu_model.c +++ b/compiler-rt/lib/builtins/cpu_model.c @@ -272,12 +272,17 @@ static void detectX86FamilyModel(unsigned EAX, unsigned *Family, } } -static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, - const unsigned *Features, - unsigned *Type, unsigned *Subtype) { +static const char * +getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, + const unsigned *Features, + unsigned *Type, unsigned *Subtype) { #define testFeature(F) \ (Features[F / 32] & (F % 32)) != 0 + // We select CPU strings to match the code in Host.cpp, but we don't use them + // in compiler-rt. + const char *CPU = 0; + switch (Family) { case 6: switch (Model) { @@ -288,13 +293,17 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, // 0Fh. All processors are manufactured using the 65 nm process. case 0x16: // Intel Celeron processor model 16h. All processors are // manufactured using the 65 nm process + CPU = "core2"; + *Type = INTEL_CORE2; + break; case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model // 17h. All processors are manufactured using the 45 nm process. // // 45nm: Penryn , Wolfdale, Yorkfield (XE) case 0x1d: // Intel Xeon processor MP. All processors are manufactured using // the 45 nm process. - *Type = INTEL_CORE2; // "penryn" + CPU = "penryn"; + *Type = INTEL_CORE2; break; case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All // processors are manufactured using the 45 nm process. @@ -302,25 +311,29 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, // As found in a Summer 2010 model iMac. case 0x1f: case 0x2e: // Nehalem EX - *Type = INTEL_COREI7; // "nehalem" + CPU = "nehalem"; + *Type = INTEL_COREI7; *Subtype = INTEL_COREI7_NEHALEM; break; case 0x25: // Intel Core i7, laptop version. case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All // processors are manufactured using the 32 nm process. case 0x2f: // Westmere EX - *Type = INTEL_COREI7; // "westmere" + CPU = "westmere"; + *Type = INTEL_COREI7; *Subtype = INTEL_COREI7_WESTMERE; break; case 0x2a: // Intel Core i7 processor. All processors are manufactured // using the 32 nm process. case 0x2d: - *Type = INTEL_COREI7; //"sandybridge" + CPU = "sandybridge"; + *Type = INTEL_COREI7; *Subtype = INTEL_COREI7_SANDYBRIDGE; break; case 0x3a: case 0x3e: // Ivy Bridge EP - *Type = INTEL_COREI7; // "ivybridge" + CPU = "ivybridge"; + *Type = INTEL_COREI7; *Subtype = INTEL_COREI7_IVYBRIDGE; break; @@ -329,7 +342,8 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x3f: case 0x45: case 0x46: - *Type = INTEL_COREI7; // "haswell" + CPU = "haswell"; + *Type = INTEL_COREI7; *Subtype = INTEL_COREI7_HASWELL; break; @@ -338,7 +352,8 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x47: case 0x4f: case 0x56: - *Type = INTEL_COREI7; // "broadwell" + CPU = "broadwell"; + *Type = INTEL_COREI7; *Subtype = INTEL_COREI7_BROADWELL; break; @@ -349,39 +364,47 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x9e: // Kaby Lake desktop case 0xa5: // Comet Lake-H/S case 0xa6: // Comet Lake-U - *Type = INTEL_COREI7; // "skylake" + CPU = "skylake"; + *Type = INTEL_COREI7; *Subtype = INTEL_COREI7_SKYLAKE; break; // Skylake Xeon: case 0x55: *Type = INTEL_COREI7; - if (testFeature(FEATURE_AVX512BF16)) - *Subtype = INTEL_COREI7_COOPERLAKE; // "cooperlake" - else if (testFeature(FEATURE_AVX512VNNI)) - *Subtype = INTEL_COREI7_CASCADELAKE; // "cascadelake" - else - *Subtype = INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512" + if (testFeature(FEATURE_AVX512BF16)) { + CPU = "cooperlake"; + *Subtype = INTEL_COREI7_COOPERLAKE; + } else if (testFeature(FEATURE_AVX512VNNI)) { + CPU = "cascadelake"; + *Subtype = INTEL_COREI7_CASCADELAKE; + } else { + CPU = "skylake-avx512"; + *Subtype = INTEL_COREI7_SKYLAKE_AVX512; + } break; // Cannonlake: case 0x66: + CPU = "cannonlake"; *Type = INTEL_COREI7; - *Subtype = INTEL_COREI7_CANNONLAKE; // "cannonlake" + *Subtype = INTEL_COREI7_CANNONLAKE; break; // Icelake: case 0x7d: case 0x7e: + CPU = "icelake-client"; *Type = INTEL_COREI7; - *Subtype = INTEL_COREI7_ICELAKE_CLIENT; // "icelake-client" + *Subtype = INTEL_COREI7_ICELAKE_CLIENT; break; // Icelake Xeon: case 0x6a: case 0x6c: + CPU = "icelake-server"; *Type = INTEL_COREI7; - *Subtype = INTEL_COREI7_ICELAKE_SERVER; // "icelake-server" + *Subtype = INTEL_COREI7_ICELAKE_SERVER; break; case 0x1c: // Most 45 nm Intel Atom processors @@ -389,8 +412,9 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x27: // 32 nm Atom Medfield case 0x35: // 32 nm Atom Midview case 0x36: // 32 nm Atom Midview + CPU = "bonnell"; *Type = INTEL_BONNELL; - break; // "bonnell" + break; // Atom Silvermont codes from the Intel software optimization guide. case 0x37: @@ -399,26 +423,32 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x5a: case 0x5d: case 0x4c: // really airmont + CPU = "silvermont"; *Type = INTEL_SILVERMONT; - break; // "silvermont" + break; // Goldmont: case 0x5c: // Apollo Lake case 0x5f: // Denverton + CPU = "goldmont"; *Type = INTEL_GOLDMONT; break; // "goldmont" case 0x7a: + CPU = "goldmont-plus"; *Type = INTEL_GOLDMONT_PLUS; break; case 0x86: + CPU = "tremont"; *Type = INTEL_TREMONT; break; case 0x57: - *Type = INTEL_KNL; // knl + CPU = "knl"; + *Type = INTEL_KNL; break; case 0x85: - *Type = INTEL_KNM; // knm + CPU = "knm"; + *Type = INTEL_KNM; break; default: // Unknown family 6 CPU. @@ -428,17 +458,22 @@ static void getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, default: break; // Unknown. } + + return CPU; } -static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, - const unsigned *Features, - unsigned *Type, unsigned *Subtype) { - // FIXME: this poorly matches the generated SubtargetFeatureKV table. There - // appears to be no way to generate the wide variety of AMD-specific targets - // from the information returned from CPUID. +static const char * +getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, + const unsigned *Features, + unsigned *Type, unsigned *Subtype) { + // We select CPU strings to match the code in Host.cpp, but we don't use them + // in compiler-rt. + const char *CPU = 0; + switch (Family) { case 16: - *Type = AMDFAM10H; // "amdfam10" + CPU = "amdfam10"; + *Type = AMDFAM10H; switch (Model) { case 2: *Subtype = AMDFAM10H_BARCELONA; @@ -452,44 +487,54 @@ static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, } break; case 20: + CPU = "btver1"; *Type = AMD_BTVER1; - break; // "btver1"; + break; case 21: + CPU = "bdver1"; *Type = AMDFAM15H; if (Model >= 0x60 && Model <= 0x7f) { + CPU = "bdver4"; *Subtype = AMDFAM15H_BDVER4; - break; // "bdver4"; 60h-7Fh: Excavator + break; // 60h-7Fh: Excavator } if (Model >= 0x30 && Model <= 0x3f) { + CPU = "bdver3"; *Subtype = AMDFAM15H_BDVER3; - break; // "bdver3"; 30h-3Fh: Steamroller + break; // 30h-3Fh: Steamroller } if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) { + CPU = "bdver2"; *Subtype = AMDFAM15H_BDVER2; - break; // "bdver2"; 02h, 10h-1Fh: Piledriver + break; // 02h, 10h-1Fh: Piledriver } if (Model <= 0x0f) { *Subtype = AMDFAM15H_BDVER1; - break; // "bdver1"; 00h-0Fh: Bulldozer + break; // 00h-0Fh: Bulldozer } break; case 22: + CPU = "btver2"; *Type = AMD_BTVER2; - break; // "btver2" + break; case 23: + CPU = "znver1"; *Type = AMDFAM17H; if ((Model >= 0x30 && Model <= 0x3f) || Model == 0x71) { + CPU = "znver2"; *Subtype = AMDFAM17H_ZNVER2; - break; // "znver2"; 30h-3fh, 71h: Zen2 + break; // 30h-3fh, 71h: Zen2 } if (Model <= 0x0f) { *Subtype = AMDFAM17H_ZNVER1; - break; // "znver1"; 00h-0Fh: Zen1 + break; // 00h-0Fh: Zen1 } break; default: - break; // "generic" + break; // Unknown AMD CPU. } + + return CPU; } static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf, From ea84dc9500df383b4fe07199134033f358411e59 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 12 Jul 2020 12:58:17 -0700 Subject: [PATCH 054/771] [X86] Add CPU string output to getIntelProcessorTypeAndSubtype/getAMDProcessorTypeAndSubtype in Host.cpp Rather than converting type/subtype into strings, just directly select the string as part of family/model decoding. This avoids the need for creating fake Type/SubTypes for CPUs not supported by compiler-rtl. I've left the Type/SubType in place where it matches compiler-rt so that the code can be diffed, but the Type/SubType is no longer used by Host.cpp. compiler-rt was already updated to select strings that aren't used so the code will look similar. --- llvm/include/llvm/Support/X86TargetParser.def | 26 -- llvm/lib/Support/Host.cpp | 366 ++++++++---------- 2 files changed, 170 insertions(+), 222 deletions(-) diff --git a/llvm/include/llvm/Support/X86TargetParser.def b/llvm/include/llvm/Support/X86TargetParser.def index 4b96c66b0e290..9e9f0985d15ea 100644 --- a/llvm/include/llvm/Support/X86TargetParser.def +++ b/llvm/include/llvm/Support/X86TargetParser.def @@ -48,25 +48,6 @@ X86_CPU_TYPE_COMPAT("knm", INTEL_KNM, "knm") X86_CPU_TYPE_COMPAT("goldmont", INTEL_GOLDMONT, "goldmont") X86_CPU_TYPE_COMPAT("goldmont-plus", INTEL_GOLDMONT_PLUS, "goldmont-plus") X86_CPU_TYPE_COMPAT("tremont", INTEL_TREMONT, "tremont") -// Entries below this are not in libgcc/compiler-rt. -X86_CPU_TYPE ("i386", INTEL_i386) -X86_CPU_TYPE ("i486", INTEL_i486) -X86_CPU_TYPE ("pentium", INTEL_PENTIUM) -X86_CPU_TYPE ("pentium-mmx", INTEL_PENTIUM_MMX) -X86_CPU_TYPE ("pentiumpro", INTEL_PENTIUM_PRO) -X86_CPU_TYPE ("pentium2", INTEL_PENTIUM_II) -X86_CPU_TYPE ("pentium3", INTEL_PENTIUM_III) -X86_CPU_TYPE ("pentium4", INTEL_PENTIUM_IV) -X86_CPU_TYPE ("pentium-m", INTEL_PENTIUM_M) -X86_CPU_TYPE ("yonah", INTEL_CORE_DUO) -X86_CPU_TYPE ("nocona", INTEL_NOCONA) -X86_CPU_TYPE ("prescott", INTEL_PRESCOTT) -X86_CPU_TYPE ("i486", AMD_i486) -X86_CPU_TYPE ("pentium", AMDPENTIUM) -X86_CPU_TYPE ("athlon", AMD_ATHLON) -X86_CPU_TYPE ("athlon-xp", AMD_ATHLON_XP) -X86_CPU_TYPE ("k8", AMD_K8) -X86_CPU_TYPE ("k8-sse3", AMD_K8SSE3) // Alternate names supported by __builtin_cpu_is and target multiversioning. X86_CPU_TYPE_COMPAT_ALIAS(INTEL_BONNELL, "atom") @@ -112,13 +93,6 @@ X86_CPU_SUBTYPE_COMPAT("znver2", AMDFAM17H_ZNVER2, "znver2") X86_CPU_SUBTYPE_COMPAT("cascadelake", INTEL_COREI7_CASCADELAKE, "cascadelake") X86_CPU_SUBTYPE_COMPAT("tigerlake", INTEL_COREI7_TIGERLAKE, "tigerlake") X86_CPU_SUBTYPE_COMPAT("cooperlake", INTEL_COREI7_COOPERLAKE, "cooperlake") -// Entries below this are not in libgcc/compiler-rt. -X86_CPU_SUBTYPE ("core2", INTEL_CORE2_65) -X86_CPU_SUBTYPE ("penryn", INTEL_CORE2_45) -X86_CPU_SUBTYPE ("k6", AMDPENTIUM_K6) -X86_CPU_SUBTYPE ("k6-2", AMDPENTIUM_K62) -X86_CPU_SUBTYPE ("k6-3", AMDPENTIUM_K63) -X86_CPU_SUBTYPE ("geode", AMDPENTIUM_GEODE) #undef X86_CPU_SUBTYPE_COMPAT #undef X86_CPU_SUBTYPE diff --git a/llvm/lib/Support/Host.cpp b/llvm/lib/Support/Host.cpp index 8dc8c4e9775ac..362b5850b394a 100644 --- a/llvm/lib/Support/Host.cpp +++ b/llvm/lib/Support/Host.cpp @@ -583,7 +583,7 @@ static void detectX86FamilyModel(unsigned EAX, unsigned *Family, } } -static void +static StringRef getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, const unsigned *Features, unsigned *Type, unsigned *Subtype) { @@ -591,31 +591,33 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, return (Features[F / 32] & (1U << (F % 32))) != 0; }; + StringRef CPU; + switch (Family) { case 3: - *Type = X86::INTEL_i386; + CPU = "i386"; break; case 4: - *Type = X86::INTEL_i486; + CPU = "i486"; break; case 5: if (testFeature(X86::FEATURE_MMX)) { - *Type = X86::INTEL_PENTIUM_MMX; + CPU = "pentium-mmx"; break; } - *Type = X86::INTEL_PENTIUM; + CPU = "pentium"; break; case 6: switch (Model) { case 0x01: // Pentium Pro processor - *Type = X86::INTEL_PENTIUM_PRO; + CPU = "pentiumpro"; break; case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor, // model 03 case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor, // model 05, and Intel Celeron processor, model 05 case 0x06: // Celeron processor, model 06 - *Type = X86::INTEL_PENTIUM_II; + CPU = "pentium2"; break; case 0x07: // Pentium III processor, model 07, and Pentium III Xeon // processor, model 07 @@ -623,19 +625,19 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, // model 08, and Celeron processor, model 08 case 0x0a: // Pentium III Xeon processor, model 0Ah case 0x0b: // Pentium III processor, model 0Bh - *Type = X86::INTEL_PENTIUM_III; + CPU = "pentium3"; break; case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09. case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model // 0Dh. All processors are manufactured using the 90 nm process. case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579 // Integrated Processor with Intel QuickAssist Technology - *Type = X86::INTEL_PENTIUM_M; + CPU = "pentium-m"; break; case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model // 0Eh. All processors are manufactured using the 65 nm process. - *Type = X86::INTEL_CORE_DUO; - break; // yonah + CPU = "yonah"; + break; case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile // processor, Intel Core 2 Quad processor, Intel Core 2 Quad // mobile processor, Intel Core 2 Extreme processor, Intel @@ -643,8 +645,8 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, // 0Fh. All processors are manufactured using the 65 nm process. case 0x16: // Intel Celeron processor model 16h. All processors are // manufactured using the 65 nm process - *Type = X86::INTEL_CORE2; // "core2" - *Subtype = X86::INTEL_CORE2_65; + CPU = "core2"; + *Type = X86::INTEL_CORE2; break; case 0x17: // Intel Core 2 Extreme processor, Intel Xeon processor, model // 17h. All processors are manufactured using the 45 nm process. @@ -652,34 +654,38 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, // 45nm: Penryn , Wolfdale, Yorkfield (XE) case 0x1d: // Intel Xeon processor MP. All processors are manufactured using // the 45 nm process. - *Type = X86::INTEL_CORE2; // "penryn" - *Subtype = X86::INTEL_CORE2_45; + CPU = "penryn"; + *Type = X86::INTEL_CORE2; break; case 0x1a: // Intel Core i7 processor and Intel Xeon processor. All // processors are manufactured using the 45 nm process. case 0x1e: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz. // As found in a Summer 2010 model iMac. case 0x1f: - case 0x2e: // Nehalem EX - *Type = X86::INTEL_COREI7; // "nehalem" + case 0x2e: // Nehalem EX + CPU = "nehalem"; + *Type = X86::INTEL_COREI7; *Subtype = X86::INTEL_COREI7_NEHALEM; break; case 0x25: // Intel Core i7, laptop version. case 0x2c: // Intel Core i7 processor and Intel Xeon processor. All // processors are manufactured using the 32 nm process. case 0x2f: // Westmere EX - *Type = X86::INTEL_COREI7; // "westmere" + CPU = "westmere"; + *Type = X86::INTEL_COREI7; *Subtype = X86::INTEL_COREI7_WESTMERE; break; case 0x2a: // Intel Core i7 processor. All processors are manufactured // using the 32 nm process. case 0x2d: - *Type = X86::INTEL_COREI7; //"sandybridge" + CPU = "sandybridge"; + *Type = X86::INTEL_COREI7; *Subtype = X86::INTEL_COREI7_SANDYBRIDGE; break; case 0x3a: - case 0x3e: // Ivy Bridge EP - *Type = X86::INTEL_COREI7; // "ivybridge" + case 0x3e: // Ivy Bridge EP + CPU = "ivybridge"; + *Type = X86::INTEL_COREI7; *Subtype = X86::INTEL_COREI7_IVYBRIDGE; break; @@ -688,7 +694,8 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x3f: case 0x45: case 0x46: - *Type = X86::INTEL_COREI7; // "haswell" + CPU = "haswell"; + *Type = X86::INTEL_COREI7; *Subtype = X86::INTEL_COREI7_HASWELL; break; @@ -697,7 +704,8 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x47: case 0x4f: case 0x56: - *Type = X86::INTEL_COREI7; // "broadwell" + CPU = "broadwell"; + *Type = X86::INTEL_COREI7; *Subtype = X86::INTEL_COREI7_BROADWELL; break; @@ -708,39 +716,47 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x9e: // Kaby Lake desktop case 0xa5: // Comet Lake-H/S case 0xa6: // Comet Lake-U - *Type = X86::INTEL_COREI7; // "skylake" + CPU = "skylake"; + *Type = X86::INTEL_COREI7; *Subtype = X86::INTEL_COREI7_SKYLAKE; break; // Skylake Xeon: case 0x55: *Type = X86::INTEL_COREI7; - if (testFeature(X86::FEATURE_AVX512BF16)) - *Subtype = X86::INTEL_COREI7_COOPERLAKE; // "cooperlake" - else if (testFeature(X86::FEATURE_AVX512VNNI)) - *Subtype = X86::INTEL_COREI7_CASCADELAKE; // "cascadelake" - else - *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; // "skylake-avx512" + if (testFeature(X86::FEATURE_AVX512BF16)) { + CPU = "cooperlake"; + *Subtype = X86::INTEL_COREI7_COOPERLAKE; + } else if (testFeature(X86::FEATURE_AVX512VNNI)) { + CPU = "cascadelake"; + *Subtype = X86::INTEL_COREI7_CASCADELAKE; + } else { + CPU = "skylake-avx512"; + *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; + } break; // Cannonlake: case 0x66: + CPU = "cannonlake"; *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_CANNONLAKE; // "cannonlake" + *Subtype = X86::INTEL_COREI7_CANNONLAKE; break; // Icelake: case 0x7d: case 0x7e: + CPU = "icelake-client"; *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT; // "icelake-client" + *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT; break; // Icelake Xeon: case 0x6a: case 0x6c: + CPU = "icelake-server"; *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER; // "icelake-server" + *Subtype = X86::INTEL_COREI7_ICELAKE_SERVER; break; case 0x1c: // Most 45 nm Intel Atom processors @@ -748,8 +764,9 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x27: // 32 nm Atom Medfield case 0x35: // 32 nm Atom Midview case 0x36: // 32 nm Atom Midview + CPU = "bonnell"; *Type = X86::INTEL_BONNELL; - break; // "bonnell" + break; // Atom Silvermont codes from the Intel software optimization guide. case 0x37: @@ -758,14 +775,17 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, case 0x5a: case 0x5d: case 0x4c: // really airmont + CPU = "silvermont"; *Type = X86::INTEL_SILVERMONT; - break; // "silvermont" + break; // Goldmont: case 0x5c: // Apollo Lake case 0x5f: // Denverton + CPU = "goldmont"; *Type = X86::INTEL_GOLDMONT; - break; // "goldmont" + break; case 0x7a: + CPU = "goldmont-plus"; *Type = X86::INTEL_GOLDMONT_PLUS; break; case 0x86: @@ -773,193 +793,140 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, break; case 0x57: - *Type = X86::INTEL_KNL; // knl + CPU = "tremont"; + *Type = X86::INTEL_KNL; break; case 0x85: - *Type = X86::INTEL_KNM; // knm + CPU = "knm"; + *Type = X86::INTEL_KNM; break; default: // Unknown family 6 CPU, try to guess. + // Don't both with Type/Subtype here, they aren't used by the caller. + // They're used above to keep the code in sync with compiler-rt. // TODO detect tigerlake host from model if (testFeature(X86::FEATURE_AVX512VP2INTERSECT)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_TIGERLAKE; - break; - } - - if (testFeature(X86::FEATURE_AVX512VBMI2)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_ICELAKE_CLIENT; - break; - } - - if (testFeature(X86::FEATURE_AVX512VBMI)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_CANNONLAKE; - break; - } - - if (testFeature(X86::FEATURE_AVX512BF16)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_COOPERLAKE; - break; - } - - if (testFeature(X86::FEATURE_AVX512VNNI)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_CASCADELAKE; - break; - } - - if (testFeature(X86::FEATURE_AVX512VL)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_SKYLAKE_AVX512; - break; - } - - if (testFeature(X86::FEATURE_AVX512ER)) { - *Type = X86::INTEL_KNL; // knl - break; - } - - if (testFeature(X86::FEATURE_CLFLUSHOPT)) { - if (testFeature(X86::FEATURE_SHA)) { - *Type = X86::INTEL_GOLDMONT; - } else { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_SKYLAKE; - } - break; - } - if (testFeature(X86::FEATURE_ADX)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_BROADWELL; - break; - } - if (testFeature(X86::FEATURE_AVX2)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_HASWELL; - break; - } - if (testFeature(X86::FEATURE_AVX)) { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_SANDYBRIDGE; - break; - } - if (testFeature(X86::FEATURE_SSE4_2)) { - if (testFeature(X86::FEATURE_MOVBE)) { - *Type = X86::INTEL_SILVERMONT; - } else { - *Type = X86::INTEL_COREI7; - *Subtype = X86::INTEL_COREI7_NEHALEM; - } - break; - } - if (testFeature(X86::FEATURE_SSE4_1)) { - *Type = X86::INTEL_CORE2; // "penryn" - *Subtype = X86::INTEL_CORE2_45; - break; - } - if (testFeature(X86::FEATURE_SSSE3)) { - if (testFeature(X86::FEATURE_MOVBE)) { - *Type = X86::INTEL_BONNELL; // "bonnell" - } else { - *Type = X86::INTEL_CORE2; // "core2" - *Subtype = X86::INTEL_CORE2_65; - } - break; - } - if (testFeature(X86::FEATURE_64BIT)) { - *Type = X86::INTEL_CORE2; // "core2" - *Subtype = X86::INTEL_CORE2_65; - break; - } - if (testFeature(X86::FEATURE_SSE3)) { - *Type = X86::INTEL_CORE_DUO; - break; + CPU = "tigerlake"; + } else if (testFeature(X86::FEATURE_AVX512VBMI2)) { + CPU = "icelake-client"; + } else if (testFeature(X86::FEATURE_AVX512VBMI)) { + CPU = "cannonlake"; + } else if (testFeature(X86::FEATURE_AVX512BF16)) { + CPU = "cooperlake"; + } else if (testFeature(X86::FEATURE_AVX512VNNI)) { + CPU = "cascadelake"; + } else if (testFeature(X86::FEATURE_AVX512VL)) { + CPU = "skylake-avx512"; + } else if (testFeature(X86::FEATURE_AVX512ER)) { + CPU = "knl"; + } else if (testFeature(X86::FEATURE_CLFLUSHOPT)) { + if (testFeature(X86::FEATURE_SHA)) + CPU = "goldmont"; + else + CPU = "skylake"; + } else if (testFeature(X86::FEATURE_ADX)) { + CPU = "broadwell"; + } else if (testFeature(X86::FEATURE_AVX2)) { + CPU = "haswell"; + } else if (testFeature(X86::FEATURE_AVX)) { + CPU = "sandybridge"; + } else if (testFeature(X86::FEATURE_SSE4_2)) { + if (testFeature(X86::FEATURE_MOVBE)) + CPU = "silvermont"; + else + CPU = "nehalem"; + } else if (testFeature(X86::FEATURE_SSE4_1)) { + CPU = "penryn"; + } else if (testFeature(X86::FEATURE_SSSE3)) { + if (testFeature(X86::FEATURE_MOVBE)) + CPU = "bonnell"; + else + CPU = "core2"; + } else if (testFeature(X86::FEATURE_64BIT)) { + CPU = "core2"; + } else if (testFeature(X86::FEATURE_SSE3)) { + CPU = "yonah"; + } else if (testFeature(X86::FEATURE_SSE2)) { + CPU = "pentium-m"; + } else if (testFeature(X86::FEATURE_SSE)) { + CPU = "pentium3"; + } else if (testFeature(X86::FEATURE_MMX)) { + CPU = "pentium2"; + } else { + CPU = "pentiumpro"; } - if (testFeature(X86::FEATURE_SSE2)) { - *Type = X86::INTEL_PENTIUM_M; - break; - } - if (testFeature(X86::FEATURE_SSE)) { - *Type = X86::INTEL_PENTIUM_III; - break; - } - if (testFeature(X86::FEATURE_MMX)) { - *Type = X86::INTEL_PENTIUM_II; - break; - } - *Type = X86::INTEL_PENTIUM_PRO; break; } break; case 15: { if (testFeature(X86::FEATURE_64BIT)) { - *Type = X86::INTEL_NOCONA; + CPU = "nocona"; break; } if (testFeature(X86::FEATURE_SSE3)) { - *Type = X86::INTEL_PRESCOTT; + CPU = "prescott"; break; } - *Type = X86::INTEL_PENTIUM_IV; + CPU = "pentium4"; break; } default: - break; /*"generic"*/ + break; // Unknown. } + + return CPU; } -static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, - const unsigned *Features, - unsigned *Type, unsigned *Subtype) { +static StringRef +getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, + const unsigned *Features, + unsigned *Type, unsigned *Subtype) { auto testFeature = [&](unsigned F) { return (Features[F / 32] & (1U << (F % 32))) != 0; }; - // FIXME: this poorly matches the generated SubtargetFeatureKV table. There - // appears to be no way to generate the wide variety of AMD-specific targets - // from the information returned from CPUID. + StringRef CPU; + switch (Family) { case 4: - *Type = X86::AMD_i486; + CPU = "i486"; break; case 5: - *Type = X86::AMDPENTIUM; + CPU = "pentium"; switch (Model) { case 6: case 7: - *Subtype = X86::AMDPENTIUM_K6; - break; // "k6" + CPU = "k6"; + break; case 8: - *Subtype = X86::AMDPENTIUM_K62; - break; // "k6-2" + CPU = "k6-2"; + break; case 9: case 13: - *Subtype = X86::AMDPENTIUM_K63; - break; // "k6-3" + CPU = "k6-3"; + break; case 10: - *Subtype = X86::AMDPENTIUM_GEODE; - break; // "geode" + CPU = "geode"; + break; } break; case 6: if (testFeature(X86::FEATURE_SSE)) { - *Type = X86::AMD_ATHLON_XP; - break; // "athlon-xp" + CPU = "athlon-xp"; + break; } - *Type = X86::AMD_ATHLON; - break; // "athlon" + CPU = "athlon"; + break; case 15: if (testFeature(X86::FEATURE_SSE3)) { - *Type = X86::AMD_K8SSE3; - break; // "k8-sse3" + CPU = "k8-sse3"; + break; } - *Type = X86::AMD_K8; - break; // "k8" + CPU = "k8"; + break; case 16: + CPU = "amdfam10"; *Type = X86::AMDFAM10H; // "amdfam10" switch (Model) { case 2: @@ -974,44 +941,54 @@ static void getAMDProcessorTypeAndSubtype(unsigned Family, unsigned Model, } break; case 20: + CPU = "btver1"; *Type = X86::AMD_BTVER1; - break; // "btver1"; + break; case 21: + CPU = "bdver1"; *Type = X86::AMDFAM15H; if (Model >= 0x60 && Model <= 0x7f) { + CPU = "bdver4"; *Subtype = X86::AMDFAM15H_BDVER4; - break; // "bdver4"; 60h-7Fh: Excavator + break; // 60h-7Fh: Excavator } if (Model >= 0x30 && Model <= 0x3f) { + CPU = "bdver3"; *Subtype = X86::AMDFAM15H_BDVER3; - break; // "bdver3"; 30h-3Fh: Steamroller + break; // 30h-3Fh: Steamroller } if ((Model >= 0x10 && Model <= 0x1f) || Model == 0x02) { + CPU = "bdver2"; *Subtype = X86::AMDFAM15H_BDVER2; - break; // "bdver2"; 02h, 10h-1Fh: Piledriver + break; // 02h, 10h-1Fh: Piledriver } if (Model <= 0x0f) { *Subtype = X86::AMDFAM15H_BDVER1; - break; // "bdver1"; 00h-0Fh: Bulldozer + break; // 00h-0Fh: Bulldozer } break; case 22: + CPU = "btver2"; *Type = X86::AMD_BTVER2; - break; // "btver2" + break; case 23: + CPU = "znver1"; *Type = X86::AMDFAM17H; if ((Model >= 0x30 && Model <= 0x3f) || Model == 0x71) { + CPU = "znver2"; *Subtype = X86::AMDFAM17H_ZNVER2; - break; // "znver2"; 30h-3fh, 71h: Zen2 + break; // 30h-3fh, 71h: Zen2 } if (Model <= 0x0f) { *Subtype = X86::AMDFAM17H_ZNVER1; - break; // "znver1"; 00h-0Fh: Zen1 + break; // 00h-0Fh: Zen1 } break; default: - break; // "generic" + break; // Unknown AMD CPU. } + + return CPU; } static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf, @@ -1161,26 +1138,23 @@ StringRef sys::getHostCPUName() { detectX86FamilyModel(EAX, &Family, &Model); getAvailableFeatures(ECX, EDX, MaxLeaf, Features); + // These aren't consumed in this file, but we try to keep some source code the + // same or similar to compiler-rt. unsigned Type = 0; unsigned Subtype = 0; + StringRef CPU; + if (Vendor == SIG_INTEL) { - getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype); + CPU = getIntelProcessorTypeAndSubtype(Family, Model, Features, &Type, + &Subtype); } else if (Vendor == SIG_AMD) { - getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, &Subtype); + CPU = getAMDProcessorTypeAndSubtype(Family, Model, Features, &Type, + &Subtype); } - // Check subtypes first since those are more specific. -#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \ - if (Subtype == X86::ENUM) \ - return ARCHNAME; -#include "llvm/Support/X86TargetParser.def" - - // Now check types. -#define X86_CPU_TYPE(ARCHNAME, ENUM) \ - if (Type == X86::ENUM) \ - return ARCHNAME; -#include "llvm/Support/X86TargetParser.def" + if (!CPU.empty()) + return CPU; return "generic"; } From 90c577a113e97212e02d5956d6db45e701e3552f Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 12 Jul 2020 12:58:23 -0700 Subject: [PATCH 055/771] [X86] Remove model number based detection for 'pentiumpro', 'pentium2', 'pentium3', 'pentium-m', and 'yonah' from getHostCPUName. For model 6 CPUs, we have a fallback detection method based on available features. That mechanism should be enough to detect these early family 6 CPUs as they only differ in the features used by the detection anyway. --- llvm/lib/Support/Host.cpp | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/llvm/lib/Support/Host.cpp b/llvm/lib/Support/Host.cpp index 362b5850b394a..658c1ee74cfec 100644 --- a/llvm/lib/Support/Host.cpp +++ b/llvm/lib/Support/Host.cpp @@ -609,35 +609,6 @@ getIntelProcessorTypeAndSubtype(unsigned Family, unsigned Model, break; case 6: switch (Model) { - case 0x01: // Pentium Pro processor - CPU = "pentiumpro"; - break; - case 0x03: // Intel Pentium II OverDrive processor, Pentium II processor, - // model 03 - case 0x05: // Pentium II processor, model 05, Pentium II Xeon processor, - // model 05, and Intel Celeron processor, model 05 - case 0x06: // Celeron processor, model 06 - CPU = "pentium2"; - break; - case 0x07: // Pentium III processor, model 07, and Pentium III Xeon - // processor, model 07 - case 0x08: // Pentium III processor, model 08, Pentium III Xeon processor, - // model 08, and Celeron processor, model 08 - case 0x0a: // Pentium III Xeon processor, model 0Ah - case 0x0b: // Pentium III processor, model 0Bh - CPU = "pentium3"; - break; - case 0x09: // Intel Pentium M processor, Intel Celeron M processor model 09. - case 0x0d: // Intel Pentium M processor, Intel Celeron M processor, model - // 0Dh. All processors are manufactured using the 90 nm process. - case 0x15: // Intel EP80579 Integrated Processor and Intel EP80579 - // Integrated Processor with Intel QuickAssist Technology - CPU = "pentium-m"; - break; - case 0x0e: // Intel Core Duo processor, Intel Core Solo processor, model - // 0Eh. All processors are manufactured using the 65 nm process. - CPU = "yonah"; - break; case 0x0f: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile // processor, Intel Core 2 Quad processor, Intel Core 2 Quad // mobile processor, Intel Core 2 Extreme processor, Intel From 572c2905aeaef00a6fedfc4c54f21856ba4cc34e Mon Sep 17 00:00:00 2001 From: River Riddle Date: Sun, 12 Jul 2020 14:11:39 -0700 Subject: [PATCH 056/771] [mlir][ODS] Add support for specifying the namespace of an interface. The namespace can be specified using the `cppNamespace` field. This matches the functionality already present on dialects, enums, etc. This fixes problems with using interfaces on operations in a different namespace than the interface was defined in. Differential Revision: https://reviews.llvm.org/D83604 --- mlir/include/mlir/IR/OpAsmInterface.td | 1 + mlir/include/mlir/IR/OpBase.td | 7 +++++++ mlir/include/mlir/IR/OpImplementation.h | 3 +-- mlir/include/mlir/IR/SymbolInterfaces.td | 1 + mlir/include/mlir/IR/SymbolTable.h | 3 +-- mlir/include/mlir/Interfaces/CallInterfaces.h | 3 ++- mlir/include/mlir/Interfaces/CallInterfaces.td | 2 ++ .../mlir/Interfaces/ControlFlowInterfaces.h | 13 +++++++------ .../mlir/Interfaces/ControlFlowInterfaces.td | 4 ++++ mlir/include/mlir/Interfaces/CopyOpInterface.h | 5 +---- mlir/include/mlir/Interfaces/CopyOpInterface.td | 1 + .../mlir/Interfaces/DerivedAttributeOpInterface.h | 3 +-- .../Interfaces/DerivedAttributeOpInterface.td | 1 + .../mlir/Interfaces/InferTypeOpInterface.h | 5 +++-- .../mlir/Interfaces/InferTypeOpInterface.td | 2 ++ mlir/include/mlir/Interfaces/LoopLikeInterface.h | 5 +---- mlir/include/mlir/Interfaces/LoopLikeInterface.td | 1 + .../mlir/Interfaces/SideEffectInterfaces.h | 14 +++++++------- .../mlir/Interfaces/SideEffectInterfaces.td | 7 +++++++ .../mlir/Interfaces/VectorUnrollInterface.h | 5 +---- .../mlir/Interfaces/VectorUnrollInterface.td | 1 + mlir/include/mlir/Interfaces/ViewLikeInterface.h | 5 +---- mlir/include/mlir/Interfaces/ViewLikeInterface.td | 1 + mlir/include/mlir/TableGen/Interfaces.h | 3 +++ mlir/include/mlir/TableGen/OpTrait.h | 2 +- mlir/include/mlir/TableGen/SideEffects.h | 2 +- mlir/lib/TableGen/Interfaces.cpp | 5 +++++ mlir/lib/TableGen/OpTrait.cpp | 9 ++++++--- mlir/lib/TableGen/Operator.cpp | 2 +- mlir/lib/TableGen/SideEffects.cpp | 8 ++++++-- mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp | 7 ++++--- mlir/tools/mlir-tblgen/OpInterfacesGen.cpp | 15 ++++++++++++++- 32 files changed, 96 insertions(+), 50 deletions(-) diff --git a/mlir/include/mlir/IR/OpAsmInterface.td b/mlir/include/mlir/IR/OpAsmInterface.td index 752536a9e9a10..ec50288348c4c 100644 --- a/mlir/include/mlir/IR/OpAsmInterface.td +++ b/mlir/include/mlir/IR/OpAsmInterface.td @@ -22,6 +22,7 @@ def OpAsmOpInterface : OpInterface<"OpAsmOpInterface"> { This interface provides hooks to interact with the AsmPrinter and AsmParser classes. }]; + let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<[{ diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td index 4344d075bc34c..9cc57a6172894 100644 --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -1803,6 +1803,12 @@ class Interface { // The name given to the c++ interface class. string cppClassName = name; + // The C++ namespace that this interface should be placed into. + // + // To specify nested namespaces, use "::" as the delimiter, e.g., given + // "A::B", ops will be placed in `namespace A { namespace B { } }`. + string cppNamespace = ""; + // The list of methods defined by this interface. list methods = []; @@ -1838,6 +1844,7 @@ class DeclareOpInterfaceMethods { let description = interface.description; let cppClassName = interface.cppClassName; + let cppNamespace = interface.cppNamespace; let methods = interface.methods; // This field contains a set of method names that should always have their diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h index 126d20eacbe49..20660be4347c1 100644 --- a/mlir/include/mlir/IR/OpImplementation.h +++ b/mlir/include/mlir/IR/OpImplementation.h @@ -764,6 +764,7 @@ class OpAsmDialectInterface virtual void getAsmBlockArgumentNames(Block *block, OpAsmSetValueNameFn setNameFn) const {} }; +} // end namespace mlir //===--------------------------------------------------------------------===// // Operation OpAsm interface. @@ -772,6 +773,4 @@ class OpAsmDialectInterface /// The OpAsmOpInterface, see OpAsmInterface.td for more details. #include "mlir/IR/OpAsmInterface.h.inc" -} // end namespace mlir - #endif diff --git a/mlir/include/mlir/IR/SymbolInterfaces.td b/mlir/include/mlir/IR/SymbolInterfaces.td index 86b33aa36a607..148551324868a 100644 --- a/mlir/include/mlir/IR/SymbolInterfaces.td +++ b/mlir/include/mlir/IR/SymbolInterfaces.td @@ -27,6 +27,7 @@ def Symbol : OpInterface<"SymbolOpInterface"> { See [Symbols and SymbolTables](SymbolsAndSymbolTables.md) for more details and constraints on `Symbol` operations. }]; + let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<"Returns the name of this symbol.", diff --git a/mlir/include/mlir/IR/SymbolTable.h b/mlir/include/mlir/IR/SymbolTable.h index 0b035836ec61d..7e52011f81ffb 100644 --- a/mlir/include/mlir/IR/SymbolTable.h +++ b/mlir/include/mlir/IR/SymbolTable.h @@ -252,10 +252,9 @@ class SymbolTable : public TraitBase { }; } // end namespace OpTrait +} // end namespace mlir /// Include the generated symbol interfaces. #include "mlir/IR/SymbolInterfaces.h.inc" -} // end namespace mlir - #endif // MLIR_IR_SYMBOLTABLE_H diff --git a/mlir/include/mlir/Interfaces/CallInterfaces.h b/mlir/include/mlir/Interfaces/CallInterfaces.h index ddfd5a942e49f..cc8e26eceba3f 100644 --- a/mlir/include/mlir/Interfaces/CallInterfaces.h +++ b/mlir/include/mlir/Interfaces/CallInterfaces.h @@ -23,8 +23,9 @@ namespace mlir { struct CallInterfaceCallable : public PointerUnion { using PointerUnion::PointerUnion; }; +} // end namespace mlir +/// Include the generated interface declarations. #include "mlir/Interfaces/CallInterfaces.h.inc" -} // end namespace mlir #endif // MLIR_INTERFACES_CALLINTERFACES_H diff --git a/mlir/include/mlir/Interfaces/CallInterfaces.td b/mlir/include/mlir/Interfaces/CallInterfaces.td index 18d927571d413..7db6730c5e992 100644 --- a/mlir/include/mlir/Interfaces/CallInterfaces.td +++ b/mlir/include/mlir/Interfaces/CallInterfaces.td @@ -29,6 +29,7 @@ def CallOpInterface : OpInterface<"CallOpInterface"> { indirect calls to other operations `call_indirect %foo`. An operation that uses this interface, must *not* also provide the `CallableOpInterface`. }]; + let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<[{ @@ -70,6 +71,7 @@ def CallableOpInterface : OpInterface<"CallableOpInterface"> { `%foo = dialect.create_function(...)`. These operations may only contain a single region, or subroutine. }]; + let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<[{ diff --git a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.h b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.h index e18c46f745a2f..7e609ca13a097 100644 --- a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.h +++ b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.h @@ -70,12 +70,6 @@ class RegionSuccessor { ValueRange inputs; }; -//===----------------------------------------------------------------------===// -// ControlFlow Interfaces -//===----------------------------------------------------------------------===// - -#include "mlir/Interfaces/ControlFlowInterfaces.h.inc" - //===----------------------------------------------------------------------===// // ControlFlow Traits //===----------------------------------------------------------------------===// @@ -101,4 +95,11 @@ struct ReturnLike : public TraitBase { } // end namespace mlir +//===----------------------------------------------------------------------===// +// ControlFlow Interfaces +//===----------------------------------------------------------------------===// + +/// Include the generated interface declarations. +#include "mlir/Interfaces/ControlFlowInterfaces.h.inc" + #endif // MLIR_INTERFACES_CONTROLFLOWINTERFACES_H diff --git a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td index 34c7bade6fe12..8b5a0b769ab17 100644 --- a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td +++ b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td @@ -25,6 +25,8 @@ def BranchOpInterface : OpInterface<"BranchOpInterface"> { This interface provides information for branching terminator operations, i.e. terminator operations with successors. }]; + let cppNamespace = "::mlir"; + let methods = [ InterfaceMethod<[{ Returns a mutable range of operands that correspond to the arguments of @@ -96,6 +98,8 @@ def RegionBranchOpInterface : OpInterface<"RegionBranchOpInterface"> { branching behavior between held regions, i.e. this interface allows for expressing control flow information for region holding operations. }]; + let cppNamespace = "::mlir"; + let methods = [ InterfaceMethod<[{ Returns the operands of this operation used as the entry arguments when diff --git a/mlir/include/mlir/Interfaces/CopyOpInterface.h b/mlir/include/mlir/Interfaces/CopyOpInterface.h index d6dc409c2471c..2f38eb326b53e 100644 --- a/mlir/include/mlir/Interfaces/CopyOpInterface.h +++ b/mlir/include/mlir/Interfaces/CopyOpInterface.h @@ -15,10 +15,7 @@ #include "mlir/IR/OpDefinition.h" -namespace mlir { - +/// Include the generated interface declarations. #include "mlir/Interfaces/CopyOpInterface.h.inc" -} // namespace mlir - #endif // MLIR_INTERFACES_COPYOPINTERFACE_H_ diff --git a/mlir/include/mlir/Interfaces/CopyOpInterface.td b/mlir/include/mlir/Interfaces/CopyOpInterface.td index 658474d70d86d..a503abc185d90 100644 --- a/mlir/include/mlir/Interfaces/CopyOpInterface.td +++ b/mlir/include/mlir/Interfaces/CopyOpInterface.td @@ -19,6 +19,7 @@ def CopyOpInterface : OpInterface<"CopyOpInterface"> { let description = [{ A copy-like operation is one that copies from source value to target value. }]; + let cppNamespace = "::mlir"; let methods = [ InterfaceMethod< diff --git a/mlir/include/mlir/Interfaces/DerivedAttributeOpInterface.h b/mlir/include/mlir/Interfaces/DerivedAttributeOpInterface.h index debafc2438d28..63cd09f5bc42c 100644 --- a/mlir/include/mlir/Interfaces/DerivedAttributeOpInterface.h +++ b/mlir/include/mlir/Interfaces/DerivedAttributeOpInterface.h @@ -15,8 +15,7 @@ #include "mlir/IR/OpDefinition.h" -namespace mlir { +/// Include the generated interface declarations. #include "mlir/Interfaces/DerivedAttributeOpInterface.h.inc" -} // namespace mlir #endif // MLIR_INTERFACES_DERIVEDATTRIBUTEOPINTERFACE_H_ diff --git a/mlir/include/mlir/Interfaces/DerivedAttributeOpInterface.td b/mlir/include/mlir/Interfaces/DerivedAttributeOpInterface.td index e6f370752bcf2..92c901840790e 100644 --- a/mlir/include/mlir/Interfaces/DerivedAttributeOpInterface.td +++ b/mlir/include/mlir/Interfaces/DerivedAttributeOpInterface.td @@ -23,6 +23,7 @@ def DerivedAttributeOpInterface : OpInterface<"DerivedAttributeOpInterface"> { from information of the operation. ODS generates convenience accessors for derived attributes and can be used to simplify translations. }]; + let cppNamespace = "::mlir"; let methods = [ StaticInterfaceMethod< diff --git a/mlir/include/mlir/Interfaces/InferTypeOpInterface.h b/mlir/include/mlir/Interfaces/InferTypeOpInterface.h index 67faeb56a51c9..1ae4aa688c84f 100644 --- a/mlir/include/mlir/Interfaces/InferTypeOpInterface.h +++ b/mlir/include/mlir/Interfaces/InferTypeOpInterface.h @@ -95,8 +95,6 @@ LogicalResult inferReturnTensorTypes( LogicalResult verifyInferredResultTypes(Operation *op); } // namespace detail -#include "mlir/Interfaces/InferTypeOpInterface.h.inc" - namespace OpTrait { /// Tensor type inference trait that constructs a tensor from the inferred @@ -119,4 +117,7 @@ class InferTensorType : public TraitBase { } // namespace OpTrait } // namespace mlir +/// Include the generated interface declarations. +#include "mlir/Interfaces/InferTypeOpInterface.h.inc" + #endif // MLIR_INTERFACES_INFERTYPEOPINTERFACE_H_ diff --git a/mlir/include/mlir/Interfaces/InferTypeOpInterface.td b/mlir/include/mlir/Interfaces/InferTypeOpInterface.td index 723cf99d38b31..c5132986ec976 100644 --- a/mlir/include/mlir/Interfaces/InferTypeOpInterface.td +++ b/mlir/include/mlir/Interfaces/InferTypeOpInterface.td @@ -25,6 +25,7 @@ def InferTypeOpInterface : OpInterface<"InferTypeOpInterface"> { Interface to infer the return types for an operation that could be used during op construction, verification or type inference. }]; + let cppNamespace = "::mlir"; let methods = [ StaticInterfaceMethod< @@ -73,6 +74,7 @@ def InferShapedTypeOpInterface : OpInterface<"InferShapedTypeOpInterface"> { The components consists of element type, shape and raw attribute. }]; + let cppNamespace = "::mlir"; let methods = [ StaticInterfaceMethod< diff --git a/mlir/include/mlir/Interfaces/LoopLikeInterface.h b/mlir/include/mlir/Interfaces/LoopLikeInterface.h index 5891470c9c6e1..48399ad0d53a8 100644 --- a/mlir/include/mlir/Interfaces/LoopLikeInterface.h +++ b/mlir/include/mlir/Interfaces/LoopLikeInterface.h @@ -15,10 +15,7 @@ #include "mlir/IR/OpDefinition.h" -namespace mlir { - +/// Include the generated interface declarations. #include "mlir/Interfaces/LoopLikeInterface.h.inc" -} // namespace mlir - #endif // MLIR_INTERFACES_LOOPLIKEINTERFACE_H_ diff --git a/mlir/include/mlir/Interfaces/LoopLikeInterface.td b/mlir/include/mlir/Interfaces/LoopLikeInterface.td index cc05030352e74..0e4191b97f97a 100644 --- a/mlir/include/mlir/Interfaces/LoopLikeInterface.td +++ b/mlir/include/mlir/Interfaces/LoopLikeInterface.td @@ -20,6 +20,7 @@ def LoopLikeOpInterface : OpInterface<"LoopLikeOpInterface"> { Encodes properties of a loop. Operations that implement this interface will be considered by loop-invariant code motion. }]; + let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<[{ diff --git a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h index 76932e2ef5293..181d218838ffb 100644 --- a/mlir/include/mlir/Interfaces/SideEffectInterfaces.h +++ b/mlir/include/mlir/Interfaces/SideEffectInterfaces.h @@ -215,13 +215,6 @@ struct Read : public Effect::Base {}; struct Write : public Effect::Base {}; } // namespace MemoryEffects -//===----------------------------------------------------------------------===// -// SideEffect Interfaces -//===----------------------------------------------------------------------===// - -/// Include the definitions of the side effect interfaces. -#include "mlir/Interfaces/SideEffectInterfaces.h.inc" - //===----------------------------------------------------------------------===// // SideEffect Utilities //===----------------------------------------------------------------------===// @@ -237,4 +230,11 @@ bool wouldOpBeTriviallyDead(Operation *op); } // end namespace mlir +//===----------------------------------------------------------------------===// +// SideEffect Interfaces +//===----------------------------------------------------------------------===// + +/// Include the definitions of the side effect interfaces. +#include "mlir/Interfaces/SideEffectInterfaces.h.inc" + #endif // MLIR_INTERFACES_SIDEEFFECTS_H diff --git a/mlir/include/mlir/Interfaces/SideEffectInterfaces.td b/mlir/include/mlir/Interfaces/SideEffectInterfaces.td index 26f2a9a7e4555..2a4da16deec2d 100644 --- a/mlir/include/mlir/Interfaces/SideEffectInterfaces.td +++ b/mlir/include/mlir/Interfaces/SideEffectInterfaces.td @@ -142,6 +142,9 @@ class SideEffect { let description = [{ Encodes properties of an operation on vectors that can be unrolled. }]; + let cppNamespace = "::mlir"; let methods = [ InterfaceMethod<[{ diff --git a/mlir/include/mlir/Interfaces/ViewLikeInterface.h b/mlir/include/mlir/Interfaces/ViewLikeInterface.h index fe7dd803ccfba..8d319bbeee18f 100644 --- a/mlir/include/mlir/Interfaces/ViewLikeInterface.h +++ b/mlir/include/mlir/Interfaces/ViewLikeInterface.h @@ -15,10 +15,7 @@ #include "mlir/IR/OpDefinition.h" -namespace mlir { - +/// Include the generated interface declarations. #include "mlir/Interfaces/ViewLikeInterface.h.inc" -} // namespace mlir - #endif // MLIR_INTERFACES_VIEWLIKEINTERFACE_H_ diff --git a/mlir/include/mlir/Interfaces/ViewLikeInterface.td b/mlir/include/mlir/Interfaces/ViewLikeInterface.td index 20b03b2315b18..bb00aff488b2a 100644 --- a/mlir/include/mlir/Interfaces/ViewLikeInterface.td +++ b/mlir/include/mlir/Interfaces/ViewLikeInterface.td @@ -21,6 +21,7 @@ def ViewLikeOpInterface : OpInterface<"ViewLikeOpInterface"> { takes in a (view of) buffer (and potentially some other operands) and returns another view of buffer. }]; + let cppNamespace = "::mlir"; let methods = [ InterfaceMethod< diff --git a/mlir/include/mlir/TableGen/Interfaces.h b/mlir/include/mlir/TableGen/Interfaces.h index 4e12ed81fca12..a3462097e4802 100644 --- a/mlir/include/mlir/TableGen/Interfaces.h +++ b/mlir/include/mlir/TableGen/Interfaces.h @@ -76,6 +76,9 @@ class Interface { // Return the name of this interface. StringRef getName() const; + // Return the C++ namespace of this interface. + StringRef getCppNamespace() const; + // Return the methods of this interface. ArrayRef getMethods() const; diff --git a/mlir/include/mlir/TableGen/OpTrait.h b/mlir/include/mlir/TableGen/OpTrait.h index 69c09b600d38d..cf8c506eb9f7e 100644 --- a/mlir/include/mlir/TableGen/OpTrait.h +++ b/mlir/include/mlir/TableGen/OpTrait.h @@ -98,7 +98,7 @@ class InterfaceOpTrait : public OpTrait { OpInterface getOpInterface() const; // Returns the trait corresponding to a C++ trait class. - StringRef getTrait() const; + std::string getTrait() const; static bool classof(const OpTrait *t) { return t->getKind() == Kind::Interface; diff --git a/mlir/include/mlir/TableGen/SideEffects.h b/mlir/include/mlir/TableGen/SideEffects.h index 4680105152526..7e464476cea11 100644 --- a/mlir/include/mlir/TableGen/SideEffects.h +++ b/mlir/include/mlir/TableGen/SideEffects.h @@ -30,7 +30,7 @@ class SideEffect : public Operator::VariableDecorator { StringRef getBaseEffectName() const; // Return the name of the Interface that the effect belongs to. - StringRef getInterfaceTrait() const; + std::string getInterfaceTrait() const; // Return the name of the resource class. StringRef getResource() const; diff --git a/mlir/lib/TableGen/Interfaces.cpp b/mlir/lib/TableGen/Interfaces.cpp index 0a6dd5f6a6425..1e6101f83caba 100644 --- a/mlir/lib/TableGen/Interfaces.cpp +++ b/mlir/lib/TableGen/Interfaces.cpp @@ -84,6 +84,11 @@ StringRef Interface::getName() const { return def->getValueAsString("cppClassName"); } +// Return the C++ namespace of this interface. +StringRef Interface::getCppNamespace() const { + return def->getValueAsString("cppNamespace"); +} + // Return the methods of this interface. ArrayRef Interface::getMethods() const { return methods; } diff --git a/mlir/lib/TableGen/OpTrait.cpp b/mlir/lib/TableGen/OpTrait.cpp index b32c647b2c958..dbfd0d374b83a 100644 --- a/mlir/lib/TableGen/OpTrait.cpp +++ b/mlir/lib/TableGen/OpTrait.cpp @@ -27,7 +27,7 @@ OpTrait OpTrait::create(const llvm::Init *init) { return OpTrait(Kind::Pred, def); if (def->isSubClassOf("GenInternalOpTrait")) return OpTrait(Kind::Internal, def); - if (def->isSubClassOf("OpInterface")) + if (def->isSubClassOf("OpInterfaceTrait")) return OpTrait(Kind::Interface, def); assert(def->isSubClassOf("NativeOpTrait")); return OpTrait(Kind::Native, def); @@ -56,8 +56,11 @@ OpInterface InterfaceOpTrait::getOpInterface() const { return OpInterface(def); } -llvm::StringRef InterfaceOpTrait::getTrait() const { - return def->getValueAsString("trait"); +std::string InterfaceOpTrait::getTrait() const { + llvm::StringRef trait = def->getValueAsString("trait"); + llvm::StringRef cppNamespace = def->getValueAsString("cppNamespace"); + return cppNamespace.empty() ? trait.str() + : (cppNamespace + "::" + trait).str(); } bool InterfaceOpTrait::shouldDeclareMethods() const { diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp index 7e8b4d8160004..3dd924566a8fd 100644 --- a/mlir/lib/TableGen/Operator.cpp +++ b/mlir/lib/TableGen/Operator.cpp @@ -336,7 +336,7 @@ void tblgen::Operator::populateTypeInferenceInfo( llvm::formatv("{0}::Trait", inferTypeOpInterface).str())) return; if (const auto *opTrait = dyn_cast(&trait)) - if (opTrait->getTrait().startswith(inferTypeOpInterface)) + if (&opTrait->getDef() == inferTrait) return; if (!def.isSubClassOf("AllTypesMatch")) diff --git a/mlir/lib/TableGen/SideEffects.cpp b/mlir/lib/TableGen/SideEffects.cpp index a2116ba3c37ba..286cacfdacf8b 100644 --- a/mlir/lib/TableGen/SideEffects.cpp +++ b/mlir/lib/TableGen/SideEffects.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "mlir/TableGen/SideEffects.h" +#include "llvm/ADT/Twine.h" #include "llvm/TableGen/Record.h" using namespace mlir; @@ -24,8 +25,11 @@ StringRef SideEffect::getBaseEffectName() const { return def->getValueAsString("baseEffectName"); } -StringRef SideEffect::getInterfaceTrait() const { - return def->getValueAsString("interfaceTrait"); +std::string SideEffect::getInterfaceTrait() const { + StringRef trait = def->getValueAsString("interfaceTrait"); + StringRef cppNamespace = def->getValueAsString("cppNamespace"); + return cppNamespace.empty() ? trait.str() + : (cppNamespace + "::" + trait).str(); } StringRef SideEffect::getResource() const { diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp index dcf40691e17f4..b2b4245989b58 100644 --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -887,7 +887,8 @@ static bool canGenerateUnwrappedBuilder(Operator &op) { } static bool canInferType(Operator &op) { - return op.getTrait("InferTypeOpInterface::Trait") && op.getNumRegions() == 0; + return op.getTrait("::mlir::InferTypeOpInterface::Trait") && + op.getNumRegions() == 0; } void OpEmitter::genSeparateArgParamBuilder() { @@ -1917,7 +1918,7 @@ void OpEmitter::genOpAsmInterface() { // TODO: We could also add a flag to allow operations to opt in to this // generation, even if they only have a single operation. int numResults = op.getNumResults(); - if (numResults <= 1 || op.getTrait("OpAsmOpInterface::Trait")) + if (numResults <= 1 || op.getTrait("::mlir::OpAsmOpInterface::Trait")) return; SmallVector resultNames(numResults); @@ -1927,7 +1928,7 @@ void OpEmitter::genOpAsmInterface() { // Don't add the trait if none of the results have a valid name. if (llvm::all_of(resultNames, [](StringRef name) { return name.empty(); })) return; - opClass.addTrait("OpAsmOpInterface::Trait"); + opClass.addTrait("::mlir::OpAsmOpInterface::Trait"); // Generate the right accessor for the number of results. auto &method = opClass.newMethod("void", "getAsmResultNames", diff --git a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp index 5a5501d42b7ef..8b27bc6de7c5e 100644 --- a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp +++ b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp @@ -150,11 +150,16 @@ struct TypeInterfaceGenerator : public InterfaceGenerator { static void emitInterfaceDef(Interface interface, StringRef valueType, raw_ostream &os) { StringRef interfaceName = interface.getName(); + StringRef cppNamespace = interface.getCppNamespace(); + cppNamespace.consume_front("::"); // Insert the method definitions. bool isOpInterface = isa(interface); for (auto &method : interface.getMethods()) { - emitCPPType(method.getReturnType(), os) << interfaceName << "::"; + emitCPPType(method.getReturnType(), os); + if (!cppNamespace.empty()) + os << cppNamespace << "::"; + os << interfaceName << "::"; emitMethodNameAndArgs(method, os, valueType, /*addThisArg=*/false, /*addConst=*/!isOpInterface); @@ -287,6 +292,11 @@ void InterfaceGenerator::emitTraitDecl(Interface &interface, } void InterfaceGenerator::emitInterfaceDecl(Interface interface) { + llvm::SmallVector namespaces; + llvm::SplitString(interface.getCppNamespace(), namespaces, "::"); + for (StringRef ns : namespaces) + os << "namespace " << ns << " {\n"; + StringRef interfaceName = interface.getName(); auto interfaceTraitsName = (interfaceName + "InterfaceTraits").str(); @@ -321,6 +331,9 @@ void InterfaceGenerator::emitInterfaceDecl(Interface interface) { os << *extraDecls << "\n"; os << "};\n"; + + for (StringRef ns : llvm::reverse(namespaces)) + os << "} // namespace " << ns << "\n"; } bool InterfaceGenerator::emitInterfaceDecls() { From 0a01fc96e24b7c7de2141a2ea07593500ea34732 Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Sun, 12 Jul 2020 22:46:37 +0300 Subject: [PATCH 057/771] Revert "[TRE] allow TRE for non-capturing calls." This reverts commit f7907e9d223d8484f9afd457ba614c2db2ae4743. That commit caused error on multi-stage build. --- .../Scalar/TailRecursionElimination.cpp | 113 ++++++++++------ llvm/test/Transforms/TailCallElim/basic.ll | 7 +- .../TailCallElim/tre-multiple-exits.ll | 125 ------------------ .../tre-noncapturing-alloca-calls.ll | 74 ----------- 4 files changed, 72 insertions(+), 247 deletions(-) delete mode 100644 llvm/test/Transforms/TailCallElim/tre-multiple-exits.ll delete mode 100644 llvm/test/Transforms/TailCallElim/tre-noncapturing-alloca-calls.ll diff --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp index bfd312a52ea58..5bb1d54d7d127 100644 --- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp +++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp @@ -81,7 +81,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Local.h" using namespace llvm; #define DEBUG_TYPE "tailcallelim" @@ -93,10 +92,7 @@ STATISTIC(NumAccumAdded, "Number of accumulators introduced"); /// Scan the specified function for alloca instructions. /// If it contains any dynamic allocas, returns false. static bool canTRE(Function &F) { - // TODO: We don't do TRE if dynamic allocas are used. - // Dynamic allocas allocate stack space which should be - // deallocated before new iteration started. That is - // currently not implemented. + // Because of PR962, we don't TRE dynamic allocas. return llvm::all_of(instructions(F), [](Instruction &I) { auto *AI = dyn_cast(&I); return !AI || AI->isStaticAlloca(); @@ -189,9 +185,11 @@ struct AllocaDerivedValueTracker { }; } -static bool markTails(Function &F, OptimizationRemarkEmitter *ORE) { +static bool markTails(Function &F, bool &AllCallsAreTailCalls, + OptimizationRemarkEmitter *ORE) { if (F.callsFunctionThatReturnsTwice()) return false; + AllCallsAreTailCalls = true; // The local stack holds all alloca instructions and all byval arguments. AllocaDerivedValueTracker Tracker; @@ -274,8 +272,11 @@ static bool markTails(Function &F, OptimizationRemarkEmitter *ORE) { } } - if (!IsNoTail && Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) + if (!IsNoTail && Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) { DeferredTails.push_back(CI); + } else { + AllCallsAreTailCalls = false; + } } for (auto *SuccBB : make_range(succ_begin(BB), succ_end(BB))) { @@ -312,6 +313,8 @@ static bool markTails(Function &F, OptimizationRemarkEmitter *ORE) { LLVM_DEBUG(dbgs() << "Marked as tail call candidate: " << *CI << "\n"); CI->setTailCall(); Modified = true; + } else { + AllCallsAreTailCalls = false; } } @@ -322,16 +325,7 @@ static bool markTails(Function &F, OptimizationRemarkEmitter *ORE) { /// instruction from after the call to before the call, assuming that all /// instructions between the call and this instruction are movable. /// -static bool canMoveAboveCall(Instruction *I, CallInst *CI, AliasAnalysis *AA, - DenseMap &AllocaForValue) { - if (isa(I)) - return true; - - if (const IntrinsicInst *II = dyn_cast(I)) - if (II->getIntrinsicID() == Intrinsic::lifetime_end && - llvm::findAllocaForValue(II->getArgOperand(1), AllocaForValue)) - return true; - +static bool canMoveAboveCall(Instruction *I, CallInst *CI, AliasAnalysis *AA) { // FIXME: We can move load/store/call/free instructions above the call if the // call does not mod/ref the memory location being processed. if (I->mayHaveSideEffects()) // This also handles volatile loads. @@ -398,6 +392,7 @@ class TailRecursionEliminator { // createTailRecurseLoopHeader the first time we find a call we can eliminate. BasicBlock *HeaderBB = nullptr; SmallVector ArgumentPHIs; + bool RemovableCallsMustBeMarkedTail = false; // PHI node to store our return value. PHINode *RetPN = nullptr; @@ -419,15 +414,13 @@ class TailRecursionEliminator { // The instruction doing the accumulating. Instruction *AccumulatorRecursionInstr = nullptr; - // The cache for pairs. - DenseMap AllocaForValue; - TailRecursionEliminator(Function &F, const TargetTransformInfo *TTI, AliasAnalysis *AA, OptimizationRemarkEmitter *ORE, DomTreeUpdater &DTU) : F(F), TTI(TTI), AA(AA), ORE(ORE), DTU(DTU) {} - CallInst *findTRECandidate(Instruction *TI); + CallInst *findTRECandidate(Instruction *TI, + bool CannotTailCallElimCallsMarkedTail); void createTailRecurseLoopHeader(CallInst *CI); @@ -435,9 +428,11 @@ class TailRecursionEliminator { bool eliminateCall(CallInst *CI); - bool foldReturnAndProcessPred(ReturnInst *Ret); + bool foldReturnAndProcessPred(ReturnInst *Ret, + bool CannotTailCallElimCallsMarkedTail); - bool processReturningBlock(ReturnInst *Ret); + bool processReturningBlock(ReturnInst *Ret, + bool CannotTailCallElimCallsMarkedTail); void cleanupAndFinalize(); @@ -448,7 +443,8 @@ class TailRecursionEliminator { }; } // namespace -CallInst *TailRecursionEliminator::findTRECandidate(Instruction *TI) { +CallInst *TailRecursionEliminator::findTRECandidate( + Instruction *TI, bool CannotTailCallElimCallsMarkedTail) { BasicBlock *BB = TI->getParent(); if (&BB->front() == TI) // Make sure there is something before the terminator. @@ -468,9 +464,9 @@ CallInst *TailRecursionEliminator::findTRECandidate(Instruction *TI) { --BBI; } - assert((!CI->isTailCall() || !CI->isNoTailCall()) && - "Incompatible call site attributes(Tail,NoTail)"); - if (!CI->isTailCall()) + // If this call is marked as a tail call, and if there are dynamic allocas in + // the function, we cannot perform this optimization. + if (CI->isTailCall() && CannotTailCallElimCallsMarkedTail) return nullptr; // As a special case, detect code like this: @@ -502,13 +498,26 @@ void TailRecursionEliminator::createTailRecurseLoopHeader(CallInst *CI) { BranchInst *BI = BranchInst::Create(HeaderBB, NewEntry); BI->setDebugLoc(CI->getDebugLoc()); - // Move all fixed sized allocas from HeaderBB to NewEntry. - for (BasicBlock::iterator OEBI = HeaderBB->begin(), E = HeaderBB->end(), - NEBI = NewEntry->begin(); - OEBI != E;) - if (AllocaInst *AI = dyn_cast(OEBI++)) - if (isa(AI->getArraySize())) - AI->moveBefore(&*NEBI); + // If this function has self recursive calls in the tail position where some + // are marked tail and some are not, only transform one flavor or another. + // We have to choose whether we move allocas in the entry block to the new + // entry block or not, so we can't make a good choice for both. We make this + // decision here based on whether the first call we found to remove is + // marked tail. + // NOTE: We could do slightly better here in the case that the function has + // no entry block allocas. + RemovableCallsMustBeMarkedTail = CI->isTailCall(); + + // If this tail call is marked 'tail' and if there are any allocas in the + // entry block, move them up to the new entry block. + if (RemovableCallsMustBeMarkedTail) + // Move all fixed sized allocas from HeaderBB to NewEntry. + for (BasicBlock::iterator OEBI = HeaderBB->begin(), E = HeaderBB->end(), + NEBI = NewEntry->begin(); + OEBI != E;) + if (AllocaInst *AI = dyn_cast(OEBI++)) + if (isa(AI->getArraySize())) + AI->moveBefore(&*NEBI); // Now that we have created a new block, which jumps to the entry // block, insert a PHI node for each argument of the function. @@ -583,7 +592,7 @@ bool TailRecursionEliminator::eliminateCall(CallInst *CI) { Instruction *AccRecInstr = nullptr; BasicBlock::iterator BBI(CI); for (++BBI; &*BBI != Ret; ++BBI) { - if (canMoveAboveCall(&*BBI, CI, AA, AllocaForValue)) + if (canMoveAboveCall(&*BBI, CI, AA)) continue; // If we can't move the instruction above the call, it might be because it @@ -611,6 +620,9 @@ bool TailRecursionEliminator::eliminateCall(CallInst *CI) { if (!HeaderBB) createTailRecurseLoopHeader(CI); + if (RemovableCallsMustBeMarkedTail && !CI->isTailCall()) + return false; + // Ok, now that we know we have a pseudo-entry block WITH all of the // required PHI nodes, add entries into the PHI node for the actual // parameters passed into the tail-recursive call. @@ -660,7 +672,8 @@ bool TailRecursionEliminator::eliminateCall(CallInst *CI) { return true; } -bool TailRecursionEliminator::foldReturnAndProcessPred(ReturnInst *Ret) { +bool TailRecursionEliminator::foldReturnAndProcessPred( + ReturnInst *Ret, bool CannotTailCallElimCallsMarkedTail) { BasicBlock *BB = Ret->getParent(); bool Change = false; @@ -685,7 +698,8 @@ bool TailRecursionEliminator::foldReturnAndProcessPred(ReturnInst *Ret) { while (!UncondBranchPreds.empty()) { BranchInst *BI = UncondBranchPreds.pop_back_val(); BasicBlock *Pred = BI->getParent(); - if (CallInst *CI = findTRECandidate(BI)) { + if (CallInst *CI = + findTRECandidate(BI, CannotTailCallElimCallsMarkedTail)) { LLVM_DEBUG(dbgs() << "FOLDING: " << *BB << "INTO UNCOND BRANCH PRED: " << *Pred); FoldReturnIntoUncondBranch(Ret, BB, Pred, &DTU); @@ -706,8 +720,9 @@ bool TailRecursionEliminator::foldReturnAndProcessPred(ReturnInst *Ret) { return Change; } -bool TailRecursionEliminator::processReturningBlock(ReturnInst *Ret) { - CallInst *CI = findTRECandidate(Ret); +bool TailRecursionEliminator::processReturningBlock( + ReturnInst *Ret, bool CannotTailCallElimCallsMarkedTail) { + CallInst *CI = findTRECandidate(Ret, CannotTailCallElimCallsMarkedTail); if (!CI) return false; @@ -795,25 +810,35 @@ bool TailRecursionEliminator::eliminate(Function &F, return false; bool MadeChange = false; - MadeChange |= markTails(F, ORE); + bool AllCallsAreTailCalls = false; + MadeChange |= markTails(F, AllCallsAreTailCalls, ORE); + if (!AllCallsAreTailCalls) + return MadeChange; // If this function is a varargs function, we won't be able to PHI the args // right, so don't even try to convert it... if (F.getFunctionType()->isVarArg()) return MadeChange; - if (!canTRE(F)) - return MadeChange; + // If false, we cannot perform TRE on tail calls marked with the 'tail' + // attribute, because doing so would cause the stack size to increase (real + // TRE would deallocate variable sized allocas, TRE doesn't). + bool CanTRETailMarkedCall = canTRE(F); TailRecursionEliminator TRE(F, TTI, AA, ORE, DTU); // Change any tail recursive calls to loops. + // + // FIXME: The code generator produces really bad code when an 'escaping + // alloca' is changed from being a static alloca to being a dynamic alloca. + // Until this is resolved, disable this transformation if that would ever + // happen. This bug is PR962. for (Function::iterator BBI = F.begin(), E = F.end(); BBI != E; /*in loop*/) { BasicBlock *BB = &*BBI++; // foldReturnAndProcessPred may delete BB. if (ReturnInst *Ret = dyn_cast(BB->getTerminator())) { - bool Change = TRE.processReturningBlock(Ret); + bool Change = TRE.processReturningBlock(Ret, !CanTRETailMarkedCall); if (!Change && BB->getFirstNonPHIOrDbg() == Ret) - Change = TRE.foldReturnAndProcessPred(Ret); + Change = TRE.foldReturnAndProcessPred(Ret, !CanTRETailMarkedCall); MadeChange |= Change; } } diff --git a/llvm/test/Transforms/TailCallElim/basic.ll b/llvm/test/Transforms/TailCallElim/basic.ll index 669210da6314b..6116014a024b1 100644 --- a/llvm/test/Transforms/TailCallElim/basic.ll +++ b/llvm/test/Transforms/TailCallElim/basic.ll @@ -12,16 +12,15 @@ define void @test0() { ret void } -; Make sure that we do not do TRE if pointer to local stack -; escapes through function call. +; PR615. Make sure that we do not move the alloca so that it interferes with the tail call. define i32 @test1() { ; CHECK: i32 @test1() ; CHECK-NEXT: alloca %A = alloca i32 ; [#uses=2] store i32 5, i32* %A call void @use(i32* %A) -; CHECK: call i32 @test1 - %X = call i32 @test1() ; [#uses=1] +; CHECK: tail call i32 @test1 + %X = tail call i32 @test1() ; [#uses=1] ret i32 %X } diff --git a/llvm/test/Transforms/TailCallElim/tre-multiple-exits.ll b/llvm/test/Transforms/TailCallElim/tre-multiple-exits.ll deleted file mode 100644 index 8f69087dd879d..0000000000000 --- a/llvm/test/Transforms/TailCallElim/tre-multiple-exits.ll +++ /dev/null @@ -1,125 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s - -; This test checks that TRE would be done for only one recursive call. -; The test_multiple_exits function has three recursive calls. -; First recursive call could not be eliminated because there is -; escaped pointer to local variable. Second recursive call could -; be eliminated. Thrid recursive call could not be eliminated since -; this is not last call. Thus, test checks that TRE would be done -; for only second recursive call. - -; IR for that test was generated from the following C++ source: -; -; void capture_arg (int*); -; void test_multiple_exits (int param); -; if (param >= 0 && param < 10) { -; int temp; -; capture_arg(&temp); -; // TRE could not be done because pointer to local -; // variable "temp" is escaped. -; test_multiple_exits(param + 1); -; } else if (param >=10 && param < 20) { -; // TRE should be done. -; test_multiple_exits(param + 1); -; } else if (param >= 20 && param < 22) { -; // TRE could not be done since recursive -; // call is not last call. -; test_multiple_exits(param + 1); -; func(); -; } -; -; return; -; } - -; Function Attrs: noinline optnone uwtable -declare void @_Z11capture_argPi(i32* %param) #0 - -; Function Attrs: noinline optnone uwtable -declare void @_Z4funcv() #0 - -; Function Attrs: noinline nounwind uwtable -define dso_local void @_Z19test_multiple_exitsi(i32 %param) local_unnamed_addr #2 { -; CHECK-LABEL: @_Z19test_multiple_exitsi( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TEMP:%.*]] = alloca i32, align 4 -; CHECK-NEXT: br label [[TAILRECURSE:%.*]] -; CHECK: tailrecurse: -; CHECK-NEXT: [[PARAM_TR:%.*]] = phi i32 [ [[PARAM:%.*]], [[ENTRY:%.*]] ], [ [[ADD6:%.*]], [[IF_THEN5:%.*]] ] -; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i32 [[PARAM_TR]], 10 -; CHECK-NEXT: br i1 [[TMP0]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] -; CHECK: if.then: -; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TEMP]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[TMP1]]) #1 -; CHECK-NEXT: call void @_Z11capture_argPi(i32* nonnull [[TEMP]]) -; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[PARAM_TR]], 1 -; CHECK-NEXT: call void @_Z19test_multiple_exitsi(i32 [[ADD]]) -; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TMP1]]) #1 -; CHECK-NEXT: br label [[IF_END14:%.*]] -; CHECK: if.else: -; CHECK-NEXT: [[PARAM_OFF:%.*]] = add i32 [[PARAM_TR]], -10 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ult i32 [[PARAM_OFF]], 10 -; CHECK-NEXT: br i1 [[TMP2]], label [[IF_THEN5]], label [[IF_ELSE7:%.*]] -; CHECK: if.then5: -; CHECK-NEXT: [[ADD6]] = add nuw nsw i32 [[PARAM_TR]], 1 -; CHECK-NEXT: br label [[TAILRECURSE]] -; CHECK: if.else7: -; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[PARAM_TR]], -2 -; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 20 -; CHECK-NEXT: br i1 [[TMP4]], label [[IF_THEN11:%.*]], label [[IF_END14]] -; CHECK: if.then11: -; CHECK-NEXT: [[ADD12:%.*]] = add nsw i32 [[PARAM_TR]], 1 -; CHECK-NEXT: tail call void @_Z19test_multiple_exitsi(i32 [[ADD12]]) -; CHECK-NEXT: tail call void @_Z4funcv() -; CHECK-NEXT: ret void -; CHECK: if.end14: -; CHECK-NEXT: ret void -; -entry: - %temp = alloca i32, align 4 - %0 = icmp ult i32 %param, 10 - br i1 %0, label %if.then, label %if.else - -if.then: ; preds = %entry - %1 = bitcast i32* %temp to i8* - call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %1) #2 - call void @_Z11capture_argPi(i32* nonnull %temp) - %add = add nuw nsw i32 %param, 1 - call void @_Z19test_multiple_exitsi(i32 %add) - call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %1) #2 - br label %if.end14 - -if.else: ; preds = %entry - %param.off = add i32 %param, -10 - %2 = icmp ult i32 %param.off, 10 - br i1 %2, label %if.then5, label %if.else7 - -if.then5: ; preds = %if.else - %add6 = add nuw nsw i32 %param, 1 - call void @_Z19test_multiple_exitsi(i32 %add6) - br label %if.end14 - -if.else7: ; preds = %if.else - %3 = and i32 %param, -2 - %4 = icmp eq i32 %3, 20 - br i1 %4, label %if.then11, label %if.end14 - -if.then11: ; preds = %if.else7 - %add12 = add nsw i32 %param, 1 - call void @_Z19test_multiple_exitsi(i32 %add12) - call void @_Z4funcv() - br label %if.end14 - -if.end14: ; preds = %if.then5, %if.then11, %if.else7, %if.then - ret void -} - -; Function Attrs: argmemonly nounwind willreturn -declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2 - -; Function Attrs: argmemonly nounwind willreturn -declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2 - -attributes #0 = { nofree noinline norecurse nounwind uwtable } -attributes #1 = { nounwind uwtable } -attributes #2 = { argmemonly nounwind willreturn } diff --git a/llvm/test/Transforms/TailCallElim/tre-noncapturing-alloca-calls.ll b/llvm/test/Transforms/TailCallElim/tre-noncapturing-alloca-calls.ll deleted file mode 100644 index 2168437fc5706..0000000000000 --- a/llvm/test/Transforms/TailCallElim/tre-noncapturing-alloca-calls.ll +++ /dev/null @@ -1,74 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -tailcallelim -verify-dom-info -S | FileCheck %s - -; IR for that test was generated from the following C++ source: -; -;int count; -;__attribute__((noinline)) void globalIncrement(const int* param) { count += *param; } -; -;void test(int recurseCount) -;{ -; if (recurseCount == 0) return; -; int temp = 10; -; globalIncrement(&temp); -; test(recurseCount - 1); -;} -; - -@count = dso_local local_unnamed_addr global i32 0, align 4 - -; Function Attrs: nofree noinline norecurse nounwind uwtable -declare void @_Z15globalIncrementPKi(i32* nocapture readonly %param) #0 - -; Test that TRE could be done for recursive tail routine containing -; call to function receiving a pointer to local stack. - -; Function Attrs: nounwind uwtable -define dso_local void @_Z4testi(i32 %recurseCount) local_unnamed_addr #1 { -; CHECK-LABEL: @_Z4testi( -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TEMP:%.*]] = alloca i32, align 4 -; CHECK-NEXT: br label [[TAILRECURSE:%.*]] -; CHECK: tailrecurse: -; CHECK-NEXT: [[RECURSECOUNT_TR:%.*]] = phi i32 [ [[RECURSECOUNT:%.*]], [[ENTRY:%.*]] ], [ [[SUB:%.*]], [[IF_END:%.*]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[RECURSECOUNT_TR]], 0 -; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[TEMP]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull [[TMP0]]) -; CHECK-NEXT: store i32 10, i32* [[TEMP]], align 4 -; CHECK-NEXT: call void @_Z15globalIncrementPKi(i32* nonnull [[TEMP]]) -; CHECK-NEXT: [[SUB]] = add nsw i32 [[RECURSECOUNT_TR]], -1 -; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull [[TMP0]]) -; CHECK-NEXT: br label [[TAILRECURSE]] -; CHECK: return: -; CHECK-NEXT: ret void -; -entry: - %temp = alloca i32, align 4 - %cmp = icmp eq i32 %recurseCount, 0 - br i1 %cmp, label %return, label %if.end - -if.end: ; preds = %entry - %0 = bitcast i32* %temp to i8* - call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %0) #6 - store i32 10, i32* %temp, align 4 - call void @_Z15globalIncrementPKi(i32* nonnull %temp) - %sub = add nsw i32 %recurseCount, -1 - call void @_Z4testi(i32 %sub) - call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %0) #6 - br label %return - -return: ; preds = %entry, %if.end - ret void -} - -; Function Attrs: argmemonly nounwind willreturn -declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2 - -; Function Attrs: argmemonly nounwind willreturn -declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2 - -attributes #0 = { nofree noinline norecurse nounwind uwtable } -attributes #1 = { nounwind uwtable } -attributes #2 = { argmemonly nounwind willreturn } From 02cfa7530d9e7cfd8ea940dab4173afb7938b831 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 12 Jul 2020 20:32:26 +0200 Subject: [PATCH 058/771] Bump the default target CPU for i386-freebsd to i686 Summary: Similar to what we have done downstream, some time ago: https://svnweb.freebsd.org/changeset/base/353936 This followed some discussions on the freebsd-arch mailing lists, and most people agreed that it was a better default, and also it worked around several issues where clang generated libcalls to 64 bit atomic primitives, instead of using cmpxchg8b. Reviewers: emaste, brooks, rsmith Reviewed By: emaste Subscribers: arichardson, krytarowski, jfb, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D83645 --- clang/lib/Driver/ToolChains/Arch/X86.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Driver/ToolChains/Arch/X86.cpp b/clang/lib/Driver/ToolChains/Arch/X86.cpp index aa95c4189d1e2..2cc44c09917f5 100644 --- a/clang/lib/Driver/ToolChains/Arch/X86.cpp +++ b/clang/lib/Driver/ToolChains/Arch/X86.cpp @@ -94,6 +94,7 @@ const char *x86::getX86TargetCPU(const ArgList &Args, switch (Triple.getOS()) { case llvm::Triple::FreeBSD: + return "i686"; case llvm::Triple::NetBSD: case llvm::Triple::OpenBSD: return "i486"; From c73f425f84ad18e4b610dff7d21a5844fb0da5d7 Mon Sep 17 00:00:00 2001 From: Shinji Okumura Date: Sun, 12 Jul 2020 19:11:49 +0900 Subject: [PATCH 059/771] [Attributor] Add AAValueSimplifyCallSiteArgument::manifest Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D82861 --- .../Transforms/IPO/AttributorAttributes.cpp | 24 +++++++ llvm/test/Transforms/Attributor/range.ll | 65 +++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index dbc1541b9950e..7e9fd61eeb41e 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -4670,6 +4670,30 @@ struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating { AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A) : AAValueSimplifyFloating(IRP, A) {} + /// See AbstractAttribute::manifest(...). + ChangeStatus manifest(Attributor &A) override { + ChangeStatus Changed = ChangeStatus::UNCHANGED; + + if (SimplifiedAssociatedValue.hasValue() && + !SimplifiedAssociatedValue.getValue()) + return Changed; + + Value &V = getAssociatedValue(); + auto *C = SimplifiedAssociatedValue.hasValue() + ? dyn_cast(SimplifiedAssociatedValue.getValue()) + : UndefValue::get(V.getType()); + if (C) { + Use &U = cast(&getAnchorValue())->getArgOperandUse(getArgNo()); + // We can replace the AssociatedValue with the constant. + if (&V != C && V.getType() == C->getType()) { + if (A.changeUseAfterManifest(U, *C)) + Changed = ChangeStatus::CHANGED; + } + } + + return Changed | AAValueSimplify::manifest(A); + } + void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(value_simplify) } diff --git a/llvm/test/Transforms/Attributor/range.ll b/llvm/test/Transforms/Attributor/range.ll index 03338b4ce4999..f105bb3fad0e1 100644 --- a/llvm/test/Transforms/Attributor/range.ll +++ b/llvm/test/Transforms/Attributor/range.ll @@ -1063,6 +1063,71 @@ end: } +define i32 @func(i1 %c) { +; CHECK-LABEL: define {{[^@]+}}@func +; CHECK-SAME: (i1 [[C:%.*]]) +; CHECK-NEXT: [[RET:%.*]] = select i1 [[C]], i32 0, i32 1 +; CHECK-NEXT: ret i32 [[RET]] +; + %ret = select i1 %c, i32 0, i32 1 + ret i32 %ret +} + +define i32 @simplify_callsite_argument(i1 %d) { +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@simplify_callsite_argument +; IS__TUNIT_OPM-SAME: (i1 [[D:%.*]]) +; IS__TUNIT_OPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false +; IS__TUNIT_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT_OPM: t: +; IS__TUNIT_OPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 [[C]]) #2, !range !3 +; IS__TUNIT_OPM-NEXT: ret i32 [[RET1]] +; IS__TUNIT_OPM: f: +; IS__TUNIT_OPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 false) #2, !range !3 +; IS__TUNIT_OPM-NEXT: ret i32 [[RET2]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@simplify_callsite_argument +; IS__TUNIT_NPM-SAME: (i1 [[D:%.*]]) +; IS__TUNIT_NPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false +; IS__TUNIT_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT_NPM: t: +; IS__TUNIT_NPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 true) #1, !range !4 +; IS__TUNIT_NPM-NEXT: ret i32 [[RET1]] +; IS__TUNIT_NPM: f: +; IS__TUNIT_NPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 false) #1, !range !4 +; IS__TUNIT_NPM-NEXT: ret i32 [[RET2]] +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@simplify_callsite_argument +; IS__CGSCC_OPM-SAME: (i1 [[D:%.*]]) +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false +; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC_OPM: t: +; IS__CGSCC_OPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 [[C]]) +; IS__CGSCC_OPM-NEXT: ret i32 [[RET1]] +; IS__CGSCC_OPM: f: +; IS__CGSCC_OPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 false) +; IS__CGSCC_OPM-NEXT: ret i32 [[RET2]] +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@simplify_callsite_argument +; IS__CGSCC_NPM-SAME: (i1 [[D:%.*]]) +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false +; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC_NPM: t: +; IS__CGSCC_NPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 true) +; IS__CGSCC_NPM-NEXT: ret i32 [[RET1]] +; IS__CGSCC_NPM: f: +; IS__CGSCC_NPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 false) +; IS__CGSCC_NPM-NEXT: ret i32 [[RET2]] +; + %c = select i1 %d, i1 true, i1 false + br i1 %c, label %t, label %f +t: + %ret1 = call i32 @func(i1 %c) + ret i32 %ret1 +f: + %ret2 = call i32 @func(i1 false) + ret i32 %ret2 +} + !0 = !{i32 0, i32 10} !1 = !{i32 10, i32 100} From 111167895d47558989f9f3a593a82527b016c7e7 Mon Sep 17 00:00:00 2001 From: Logan Smith Date: Sun, 12 Jul 2020 15:38:37 -0700 Subject: [PATCH 060/771] [clang] Add -Wsuggest-override This patch adds `-Wsuggest-override`, which allows for more aggressive enforcement of modern C++ best practices, as well as better compatibility with gcc, which has had its own `-Wsuggest-override` since version 5.1. Clang already has `-Winconsistent-missing-override`, which only warns in the case where there is at least one function already marked `override` in a class. This warning strengthens that warning by suggesting the `override` keyword regardless of whether it is already present anywhere. The text between suggest-override and inconsistent-missing-override is now shared, using `TextSubstitution` for the entire diagnostic text. Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D82728 --- clang/include/clang/Basic/DiagnosticGroups.td | 7 +++- .../clang/Basic/DiagnosticSemaKinds.td | 22 ++++++++--- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Sema/SemaDeclCXX.cpp | 33 +++++++++------- .../SemaCXX/warn-suggest-destructor-override | 27 +++++++++++++ clang/test/SemaCXX/warn-suggest-override | 38 +++++++++++++++++++ 6 files changed, 107 insertions(+), 22 deletions(-) create mode 100644 clang/test/SemaCXX/warn-suggest-destructor-override create mode 100644 clang/test/SemaCXX/warn-suggest-override diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 6a50ceef41913..1e829be4028e4 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -280,9 +280,12 @@ def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", def CXX11Narrowing : DiagGroup<"c++11-narrowing">; -def CXX11WarnOverrideDestructor : +def CXX11WarnInconsistentOverrideDestructor : DiagGroup<"inconsistent-missing-destructor-override">; -def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">; +def CXX11WarnInconsistentOverrideMethod : + DiagGroup<"inconsistent-missing-override">; +def CXX11WarnSuggestOverrideDestructor : DiagGroup<"suggest-destructor-override">; +def CXX11WarnSuggestOverride : DiagGroup<"suggest-override">; // Original name of this warning in Clang def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 24e942037ecfb..71517edd6659b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2367,12 +2367,22 @@ def override_keyword_hides_virtual_member_function : Error< "%select{function|functions}1">; def err_function_marked_override_not_overriding : Error< "%0 marked 'override' but does not override any member functions">; -def warn_destructor_marked_not_override_overriding : Warning < - "%0 overrides a destructor but is not marked 'override'">, - InGroup, DefaultIgnore; -def warn_function_marked_not_override_overriding : Warning < - "%0 overrides a member function but is not marked 'override'">, - InGroup; +def warn_destructor_marked_not_override_overriding : TextSubstitution < + "%0 overrides a destructor but is not marked 'override'">; +def warn_function_marked_not_override_overriding : TextSubstitution < + "%0 overrides a member function but is not marked 'override'">; +def warn_inconsistent_destructor_marked_not_override_overriding : Warning < + "%sub{warn_destructor_marked_not_override_overriding}0">, + InGroup, DefaultIgnore; +def warn_inconsistent_function_marked_not_override_overriding : Warning < + "%sub{warn_function_marked_not_override_overriding}0">, + InGroup; +def warn_suggest_destructor_marked_not_override_overriding : Warning < + "%sub{warn_destructor_marked_not_override_overriding}0">, + InGroup, DefaultIgnore; +def warn_suggest_function_marked_not_override_overriding : Warning < + "%sub{warn_function_marked_not_override_overriding}0">, + InGroup, DefaultIgnore; def err_class_marked_final_used_as_base : Error< "base %0 is marked '%select{final|sealed}1'">; def warn_abstract_final_class : Warning< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e75ac185eb2cb..6f7ad8076718d 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6965,7 +6965,7 @@ class Sema final { /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was /// not used in the declaration of an overriding method. - void DiagnoseAbsenceOfOverrideControl(NamedDecl *D); + void DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent); /// CheckForFunctionMarkedFinal - Checks whether a virtual member function /// overrides a virtual member function marked 'final', according to diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 9cad6debc600c..515a2e9690ed1 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3045,7 +3045,7 @@ void Sema::CheckOverrideControl(NamedDecl *D) { << MD->getDeclName(); } -void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) { +void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D, bool Inconsistent) { if (D->isInvalidDecl() || D->hasAttr()) return; CXXMethodDecl *MD = dyn_cast(D); @@ -3061,12 +3061,22 @@ void Sema::DiagnoseAbsenceOfOverrideControl(NamedDecl *D) { return; if (MD->size_overridden_methods() > 0) { - unsigned DiagID = isa(MD) - ? diag::warn_destructor_marked_not_override_overriding - : diag::warn_function_marked_not_override_overriding; - Diag(MD->getLocation(), DiagID) << MD->getDeclName(); - const CXXMethodDecl *OMD = *MD->begin_overridden_methods(); - Diag(OMD->getLocation(), diag::note_overridden_virtual_function); + auto EmitDiag = [&](unsigned DiagInconsistent, unsigned DiagSuggest) { + unsigned DiagID = + Inconsistent && !Diags.isIgnored(DiagInconsistent, MD->getLocation()) + ? DiagInconsistent + : DiagSuggest; + Diag(MD->getLocation(), DiagID) << MD->getDeclName(); + const CXXMethodDecl *OMD = *MD->begin_overridden_methods(); + Diag(OMD->getLocation(), diag::note_overridden_virtual_function); + }; + if (isa(MD)) + EmitDiag( + diag::warn_inconsistent_destructor_marked_not_override_overriding, + diag::warn_suggest_destructor_marked_not_override_overriding); + else + EmitDiag(diag::warn_inconsistent_function_marked_not_override_overriding, + diag::warn_suggest_function_marked_not_override_overriding); } } @@ -6749,13 +6759,10 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { } } - if (HasMethodWithOverrideControl && - HasOverridingMethodWithoutOverrideControl) { - // At least one method has the 'override' control declared. - // Diagnose all other overridden methods which do not have 'override' - // specified on them. + if (HasOverridingMethodWithoutOverrideControl) { + bool HasInconsistentOverrideControl = HasMethodWithOverrideControl; for (auto *M : Record->methods()) - DiagnoseAbsenceOfOverrideControl(M); + DiagnoseAbsenceOfOverrideControl(M, HasInconsistentOverrideControl); } // Check the defaulted secondary comparisons after any other member functions. diff --git a/clang/test/SemaCXX/warn-suggest-destructor-override b/clang/test/SemaCXX/warn-suggest-destructor-override new file mode 100644 index 0000000000000..1cfff748678f2 --- /dev/null +++ b/clang/test/SemaCXX/warn-suggest-destructor-override @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify -Wsuggest-destructor-override + +struct A { + ~A(); + virtual void run(); +}; + +struct B : public A { + ~B(); +}; + +struct C { + virtual void run(); + virtual ~C(); // expected-note 2{{overridden virtual function is here}} +}; + +struct D : public C { + void run(); + ~D(); + // expected-warning@-1 {{'~D' overrides a destructor but is not marked 'override'}} +}; + +struct E : public C { + void run(); + virtual ~E(); + // expected-warning@-1 {{'~E' overrides a destructor but is not marked 'override'}} +}; diff --git a/clang/test/SemaCXX/warn-suggest-override b/clang/test/SemaCXX/warn-suggest-override new file mode 100644 index 0000000000000..e06c939ff001f --- /dev/null +++ b/clang/test/SemaCXX/warn-suggest-override @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify -Wsuggest-override + +struct A { + ~A(); + void run(); +}; + +struct B : public A { + ~B(); + void run(); +}; + +struct C { + virtual void run(); // expected-note 2{{overridden virtual function is here}} + virtual ~C(); +}; + +struct D : public C { + void run(); + // expected-warning@-1 {{'run()' overrides a member function but is not marked 'override'}} + ~D(); +}; + +struct E : public C { + virtual void run(); + // expected-warning@-1 {{'run()' overrides a member function but is not marked 'override'}} + virtual ~E(); +}; + +struct F : public C { + void run() override; + ~F() override; +}; + +struct G : public C { + void run() final; + ~G() final; +}; From b4dbb37f32e554e4d6f118d9ddd87717721ea664 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Sun, 12 Jul 2020 16:58:27 -0700 Subject: [PATCH 061/771] [X86] Rename X86_CPU_TYPE_COMPAT_ALIAS/X86_CPU_TYPE_COMPAT/X86_CPU_SUBTYPE_COMPAT macros. NFC Remove _COMPAT. Drop the ARCHNAME. Remove the non-COMPAT versions that are no longer needed. We now only use these macros in places where we need compatibility with libgcc/compiler-rt. So we don't need to call out _COMPAT specifically. --- clang/lib/Basic/Targets/X86.cpp | 6 +- clang/lib/CodeGen/CGBuiltin.cpp | 6 +- llvm/include/llvm/Support/X86TargetParser.def | 110 ++++++++---------- llvm/include/llvm/Support/X86TargetParser.h | 4 +- 4 files changed, 58 insertions(+), 68 deletions(-) diff --git a/clang/lib/Basic/Targets/X86.cpp b/clang/lib/Basic/Targets/X86.cpp index e280a72166451..543f232d24591 100644 --- a/clang/lib/Basic/Targets/X86.cpp +++ b/clang/lib/Basic/Targets/X86.cpp @@ -1062,9 +1062,9 @@ void X86TargetInfo::getCPUSpecificCPUDispatchFeatures( bool X86TargetInfo::validateCpuIs(StringRef FeatureStr) const { return llvm::StringSwitch(FeatureStr) #define X86_VENDOR(ENUM, STRING) .Case(STRING, true) -#define X86_CPU_TYPE_COMPAT_ALIAS(ENUM, ALIAS) .Case(ALIAS, true) -#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) .Case(STR, true) -#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) .Case(STR, true) +#define X86_CPU_TYPE_ALIAS(ENUM, ALIAS) .Case(ALIAS, true) +#define X86_CPU_TYPE(ENUM, STR) .Case(STR, true) +#define X86_CPU_SUBTYPE(ENUM, STR) .Case(STR, true) #include "llvm/Support/X86TargetParser.def" .Default(false); } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 1d81ede5dc31e..35a93a7889f40 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -11655,11 +11655,11 @@ Value *CodeGenFunction::EmitX86CpuIs(StringRef CPUStr) { std::tie(Index, Value) = StringSwitch>(CPUStr) #define X86_VENDOR(ENUM, STRING) \ .Case(STRING, {0u, static_cast(llvm::X86::ENUM)}) -#define X86_CPU_TYPE_COMPAT_ALIAS(ENUM, ALIAS) \ +#define X86_CPU_TYPE_ALIAS(ENUM, ALIAS) \ .Case(ALIAS, {1u, static_cast(llvm::X86::ENUM)}) -#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) \ +#define X86_CPU_TYPE(ENUM, STR) \ .Case(STR, {1u, static_cast(llvm::X86::ENUM)}) -#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) \ +#define X86_CPU_SUBTYPE(ENUM, STR) \ .Case(STR, {2u, static_cast(llvm::X86::ENUM)}) #include "llvm/Support/X86TargetParser.def" .Default({0, 0}); diff --git a/llvm/include/llvm/Support/X86TargetParser.def b/llvm/include/llvm/Support/X86TargetParser.def index 9e9f0985d15ea..697f8c70f962d 100644 --- a/llvm/include/llvm/Support/X86TargetParser.def +++ b/llvm/include/llvm/Support/X86TargetParser.def @@ -20,80 +20,70 @@ X86_VENDOR(VENDOR_AMD, "amd") #undef X86_VENDOR // This macro is used for cpu types present in compiler-rt/libgcc. -#ifndef X86_CPU_TYPE_COMPAT -#define X86_CPU_TYPE_COMPAT(ARCHNAME, ENUM, STR) X86_CPU_TYPE(ARCHNAME, ENUM) -#endif - #ifndef X86_CPU_TYPE -#define X86_CPU_TYPE(ARCHNAME, ENUM) +#define X86_CPU_TYPE(ENUM, STR) #endif -#ifndef X86_CPU_TYPE_COMPAT_ALIAS -#define X86_CPU_TYPE_COMPAT_ALIAS(ENUM, STR) +#ifndef X86_CPU_TYPE_ALIAS +#define X86_CPU_TYPE_ALIAS(ENUM, STR) #endif -// The first part of this list must match what is implemented in libgcc and -// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is. -X86_CPU_TYPE_COMPAT("bonnell", INTEL_BONNELL, "bonnell") -X86_CPU_TYPE_COMPAT("core2", INTEL_CORE2, "core2") -X86_CPU_TYPE_COMPAT("nehalem", INTEL_COREI7, "corei7") -X86_CPU_TYPE_COMPAT("amdfam10", AMDFAM10H, "amdfam10h") -X86_CPU_TYPE_COMPAT("bdver1", AMDFAM15H, "amdfam15h") -X86_CPU_TYPE_COMPAT("silvermont", INTEL_SILVERMONT, "silvermont") -X86_CPU_TYPE_COMPAT("knl", INTEL_KNL, "knl") -X86_CPU_TYPE_COMPAT("btver1", AMD_BTVER1, "btver1") -X86_CPU_TYPE_COMPAT("btver2", AMD_BTVER2, "btver2") -X86_CPU_TYPE_COMPAT("znver1", AMDFAM17H, "amdfam17h") -X86_CPU_TYPE_COMPAT("knm", INTEL_KNM, "knm") -X86_CPU_TYPE_COMPAT("goldmont", INTEL_GOLDMONT, "goldmont") -X86_CPU_TYPE_COMPAT("goldmont-plus", INTEL_GOLDMONT_PLUS, "goldmont-plus") -X86_CPU_TYPE_COMPAT("tremont", INTEL_TREMONT, "tremont") +// This list must match what is implemented in libgcc and compilert-rt. Clang +// uses this to know how to implement __builtin_cpu_is. +X86_CPU_TYPE(INTEL_BONNELL, "bonnell") +X86_CPU_TYPE(INTEL_CORE2, "core2") +X86_CPU_TYPE(INTEL_COREI7, "corei7") +X86_CPU_TYPE(AMDFAM10H, "amdfam10h") +X86_CPU_TYPE(AMDFAM15H, "amdfam15h") +X86_CPU_TYPE(INTEL_SILVERMONT, "silvermont") +X86_CPU_TYPE(INTEL_KNL, "knl") +X86_CPU_TYPE(AMD_BTVER1, "btver1") +X86_CPU_TYPE(AMD_BTVER2, "btver2") +X86_CPU_TYPE(AMDFAM17H, "amdfam17h") +X86_CPU_TYPE(INTEL_KNM, "knm") +X86_CPU_TYPE(INTEL_GOLDMONT, "goldmont") +X86_CPU_TYPE(INTEL_GOLDMONT_PLUS, "goldmont-plus") +X86_CPU_TYPE(INTEL_TREMONT, "tremont") // Alternate names supported by __builtin_cpu_is and target multiversioning. -X86_CPU_TYPE_COMPAT_ALIAS(INTEL_BONNELL, "atom") -X86_CPU_TYPE_COMPAT_ALIAS(AMDFAM10H, "amdfam10") -X86_CPU_TYPE_COMPAT_ALIAS(AMDFAM15H, "amdfam15") -X86_CPU_TYPE_COMPAT_ALIAS(INTEL_SILVERMONT, "slm") +X86_CPU_TYPE_ALIAS(INTEL_BONNELL, "atom") +X86_CPU_TYPE_ALIAS(AMDFAM10H, "amdfam10") +X86_CPU_TYPE_ALIAS(AMDFAM15H, "amdfam15") +X86_CPU_TYPE_ALIAS(INTEL_SILVERMONT, "slm") -#undef X86_CPU_TYPE_COMPAT_ALIAS -#undef X86_CPU_TYPE_COMPAT +#undef X86_CPU_TYPE_ALIAS #undef X86_CPU_TYPE // This macro is used for cpu subtypes present in compiler-rt/libgcc. -#ifndef X86_CPU_SUBTYPE_COMPAT -#define X86_CPU_SUBTYPE_COMPAT(ARCHNAME, ENUM, STR) X86_CPU_SUBTYPE(ARCHNAME, ENUM) -#endif - #ifndef X86_CPU_SUBTYPE -#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) +#define X86_CPU_SUBTYPE(ENUM, STR) #endif -// The first part of this list must match what is implemented in libgcc and -// compilert-rt. Clang uses this to know how to implement __builtin_cpu_is. -X86_CPU_SUBTYPE_COMPAT("nehalem", INTEL_COREI7_NEHALEM, "nehalem") -X86_CPU_SUBTYPE_COMPAT("westmere", INTEL_COREI7_WESTMERE, "westmere") -X86_CPU_SUBTYPE_COMPAT("sandybridge", INTEL_COREI7_SANDYBRIDGE, "sandybridge") -X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_BARCELONA, "barcelona") -X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_SHANGHAI, "shanghai") -X86_CPU_SUBTYPE_COMPAT("amdfam10", AMDFAM10H_ISTANBUL, "istanbul") -X86_CPU_SUBTYPE_COMPAT("bdver1", AMDFAM15H_BDVER1, "bdver1") -X86_CPU_SUBTYPE_COMPAT("bdver2", AMDFAM15H_BDVER2, "bdver2") -X86_CPU_SUBTYPE_COMPAT("bdver3", AMDFAM15H_BDVER3, "bdver3") -X86_CPU_SUBTYPE_COMPAT("bdver4", AMDFAM15H_BDVER4, "bdver4") -X86_CPU_SUBTYPE_COMPAT("znver1", AMDFAM17H_ZNVER1, "znver1") -X86_CPU_SUBTYPE_COMPAT("ivybridge", INTEL_COREI7_IVYBRIDGE, "ivybridge") -X86_CPU_SUBTYPE_COMPAT("haswell", INTEL_COREI7_HASWELL, "haswell") -X86_CPU_SUBTYPE_COMPAT("broadwell", INTEL_COREI7_BROADWELL, "broadwell") -X86_CPU_SUBTYPE_COMPAT("skylake", INTEL_COREI7_SKYLAKE, "skylake") -X86_CPU_SUBTYPE_COMPAT("skylake-avx512", INTEL_COREI7_SKYLAKE_AVX512, "skylake-avx512") -X86_CPU_SUBTYPE_COMPAT("cannonlake", INTEL_COREI7_CANNONLAKE, "cannonlake") -X86_CPU_SUBTYPE_COMPAT("icelake-client", INTEL_COREI7_ICELAKE_CLIENT, "icelake-client") -X86_CPU_SUBTYPE_COMPAT("icelake-server", INTEL_COREI7_ICELAKE_SERVER, "icelake-server") -X86_CPU_SUBTYPE_COMPAT("znver2", AMDFAM17H_ZNVER2, "znver2") -X86_CPU_SUBTYPE_COMPAT("cascadelake", INTEL_COREI7_CASCADELAKE, "cascadelake") -X86_CPU_SUBTYPE_COMPAT("tigerlake", INTEL_COREI7_TIGERLAKE, "tigerlake") -X86_CPU_SUBTYPE_COMPAT("cooperlake", INTEL_COREI7_COOPERLAKE, "cooperlake") -#undef X86_CPU_SUBTYPE_COMPAT +// This list must match what is implemented in libgcc and compilert-rt. Clang +// uses this to know how to implement __builtin_cpu_is. +X86_CPU_SUBTYPE(INTEL_COREI7_NEHALEM, "nehalem") +X86_CPU_SUBTYPE(INTEL_COREI7_WESTMERE, "westmere") +X86_CPU_SUBTYPE(INTEL_COREI7_SANDYBRIDGE, "sandybridge") +X86_CPU_SUBTYPE(AMDFAM10H_BARCELONA, "barcelona") +X86_CPU_SUBTYPE(AMDFAM10H_SHANGHAI, "shanghai") +X86_CPU_SUBTYPE(AMDFAM10H_ISTANBUL, "istanbul") +X86_CPU_SUBTYPE(AMDFAM15H_BDVER1, "bdver1") +X86_CPU_SUBTYPE(AMDFAM15H_BDVER2, "bdver2") +X86_CPU_SUBTYPE(AMDFAM15H_BDVER3, "bdver3") +X86_CPU_SUBTYPE(AMDFAM15H_BDVER4, "bdver4") +X86_CPU_SUBTYPE(AMDFAM17H_ZNVER1, "znver1") +X86_CPU_SUBTYPE(INTEL_COREI7_IVYBRIDGE, "ivybridge") +X86_CPU_SUBTYPE(INTEL_COREI7_HASWELL, "haswell") +X86_CPU_SUBTYPE(INTEL_COREI7_BROADWELL, "broadwell") +X86_CPU_SUBTYPE(INTEL_COREI7_SKYLAKE, "skylake") +X86_CPU_SUBTYPE(INTEL_COREI7_SKYLAKE_AVX512, "skylake-avx512") +X86_CPU_SUBTYPE(INTEL_COREI7_CANNONLAKE, "cannonlake") +X86_CPU_SUBTYPE(INTEL_COREI7_ICELAKE_CLIENT, "icelake-client") +X86_CPU_SUBTYPE(INTEL_COREI7_ICELAKE_SERVER, "icelake-server") +X86_CPU_SUBTYPE(AMDFAM17H_ZNVER2, "znver2") +X86_CPU_SUBTYPE(INTEL_COREI7_CASCADELAKE, "cascadelake") +X86_CPU_SUBTYPE(INTEL_COREI7_TIGERLAKE, "tigerlake") +X86_CPU_SUBTYPE(INTEL_COREI7_COOPERLAKE, "cooperlake") #undef X86_CPU_SUBTYPE diff --git a/llvm/include/llvm/Support/X86TargetParser.h b/llvm/include/llvm/Support/X86TargetParser.h index 4a4fb8ccc4ccf..66c474b5c2750 100644 --- a/llvm/include/llvm/Support/X86TargetParser.h +++ b/llvm/include/llvm/Support/X86TargetParser.h @@ -34,7 +34,7 @@ enum ProcessorVendors : unsigned { // as a proxy for what's in libgcc/compiler-rt. enum ProcessorTypes : unsigned { CPU_TYPE_DUMMY, -#define X86_CPU_TYPE(ARCHNAME, ENUM) \ +#define X86_CPU_TYPE(ENUM, STRING) \ ENUM, #include "llvm/Support/X86TargetParser.def" CPU_TYPE_MAX @@ -44,7 +44,7 @@ enum ProcessorTypes : unsigned { // as a proxy for what's in libgcc/compiler-rt. enum ProcessorSubtypes : unsigned { CPU_SUBTYPE_DUMMY, -#define X86_CPU_SUBTYPE(ARCHNAME, ENUM) \ +#define X86_CPU_SUBTYPE(ENUM, STRING) \ ENUM, #include "llvm/Support/X86TargetParser.def" CPU_SUBTYPE_MAX From 49e5f603d40083dce9c05796e3cde3a185c3beba Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 23 Mar 2020 15:07:51 -0700 Subject: [PATCH 062/771] Rename/refactor isIntegerConstantExpression to getIntegerConstantExpression There is a version that just tests (also called isIntegerConstantExpression) & whereas this version is specifically used when the value is of interest (a few call sites were actually refactored to calling the test-only version) so let's make the API look more like it. Reviewers: aaron.ballman Differential Revision: https://reviews.llvm.org/D76646 --- clang/include/clang/AST/Expr.h | 13 ++-- clang/lib/AST/ASTContext.cpp | 16 ++--- clang/lib/AST/ExprConstant.cpp | 19 +++-- clang/lib/AST/MicrosoftMangle.cpp | 6 +- clang/lib/CodeGen/CGBuiltin.cpp | 114 +++++++++++++----------------- clang/lib/CodeGen/CGExpr.cpp | 16 +++-- clang/lib/Sema/SemaAttr.cpp | 12 ++-- clang/lib/Sema/SemaChecking.cpp | 107 +++++++++++++--------------- clang/lib/Sema/SemaDecl.cpp | 8 +-- clang/lib/Sema/SemaDeclAttr.cpp | 77 ++++++++++---------- clang/lib/Sema/SemaExprCXX.cpp | 14 ++-- clang/lib/Sema/SemaOpenMP.cpp | 66 +++++++++-------- clang/lib/Sema/SemaOverload.cpp | 30 ++++---- clang/lib/Sema/SemaStmtAttr.cpp | 6 +- clang/lib/Sema/SemaType.cpp | 26 +++---- 15 files changed, 255 insertions(+), 275 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 66eafaaab715e..a42c7bb5a9f26 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -510,16 +510,15 @@ class Expr : public ValueStmt { /// semantically correspond to a bool. bool isKnownToHaveBooleanValue(bool Semantic = true) const; - /// isIntegerConstantExpr - Return true if this expression is a valid integer - /// constant expression, and, if so, return its value in Result. If not a - /// valid i-c-e, return false and fill in Loc (if specified) with the location - /// of the invalid expression. + /// isIntegerConstantExpr - Return the value if this expression is a valid + /// integer constant expression. If not a valid i-c-e, return None and fill + /// in Loc (if specified) with the location of the invalid expression. /// /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. - bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx, - SourceLocation *Loc = nullptr, - bool isEvaluated = true) const; + Optional getIntegerConstantExpr(const ASTContext &Ctx, + SourceLocation *Loc = nullptr, + bool isEvaluated = true) const; bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc = nullptr) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 2ba643f12a82f..807028885652d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -9471,17 +9471,15 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, const ConstantArrayType* CAT) -> std::pair { if (VAT) { - llvm::APSInt TheInt; + Optional TheInt; Expr *E = VAT->getSizeExpr(); - if (E && E->isIntegerConstantExpr(TheInt, *this)) - return std::make_pair(true, TheInt); - else - return std::make_pair(false, TheInt); - } else if (CAT) { - return std::make_pair(true, CAT->getSize()); - } else { - return std::make_pair(false, llvm::APInt()); + if (E && (TheInt = E->getIntegerConstantExpr(*this))) + return std::make_pair(true, *TheInt); + return std::make_pair(false, llvm::APSInt()); } + if (CAT) + return std::make_pair(true, CAT->getSize()); + return std::make_pair(false, llvm::APInt()); }; bool HaveLSize, HaveRSize; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index a4dc0ccad1e0f..011dc890496d0 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14883,16 +14883,22 @@ bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, return true; } -bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, - SourceLocation *Loc, bool isEvaluated) const { +Optional Expr::getIntegerConstantExpr(const ASTContext &Ctx, + SourceLocation *Loc, + bool isEvaluated) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); - if (Ctx.getLangOpts().CPlusPlus11) - return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); + APSInt Value; + + if (Ctx.getLangOpts().CPlusPlus11) { + if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc)) + return Value; + return None; + } if (!isIntegerConstantExpr(Ctx, Loc)) - return false; + return None; // The only possible side-effects here are due to UB discovered in the // evaluation (for instance, INT_MAX + 1). In such a case, we are still @@ -14906,8 +14912,7 @@ bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info)) llvm_unreachable("ICE cannot be evaluated!"); - Value = ExprResult.Val.getInt(); - return true; + return ExprResult.Val.getInt(); } bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const { diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 529f301e46964..09579c28061ae 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1372,9 +1372,9 @@ void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // See if this is a constant expression. - llvm::APSInt Value; - if (E->isIntegerConstantExpr(Value, Context.getASTContext())) { - mangleIntegerLiteral(Value, E->getType()->isBooleanType()); + if (Optional Value = + E->getIntegerConstantExpr(Context.getASTContext())) { + mangleIntegerLiteral(*Value, E->getType()->isBooleanType()); return; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 35a93a7889f40..3588e33714d2f 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4419,11 +4419,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } else { // If this is required to be a constant, constant fold it so that we // know that the generated intrinsic gets a ConstantInt. - llvm::APSInt Result; - bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result,getContext()); - assert(IsConst && "Constant arg isn't actually constant?"); - (void)IsConst; - ArgValue = llvm::ConstantInt::get(getLLVMContext(), Result); + ArgValue = llvm::ConstantInt::get( + getLLVMContext(), + *E->getArg(i)->getIntegerConstantExpr(getContext())); } // If the intrinsic arg type is different from the builtin arg type @@ -5596,13 +5594,14 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( SmallVectorImpl &Ops, Address PtrOp0, Address PtrOp1, llvm::Triple::ArchType Arch) { // Get the last argument, which specifies the vector type. - llvm::APSInt NeonTypeConst; const Expr *Arg = E->getArg(E->getNumArgs() - 1); - if (!Arg->isIntegerConstantExpr(NeonTypeConst, getContext())) + Optional NeonTypeConst = + Arg->getIntegerConstantExpr(getContext()); + if (!NeonTypeConst) return nullptr; // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type(NeonTypeConst.getZExtValue()); + NeonTypeFlags Type(NeonTypeConst->getZExtValue()); bool Usgn = Type.isUnsigned(); bool Quad = Type.isQuad(); const bool HasLegalHalfType = getTarget().hasLegalHalfType(); @@ -6885,10 +6884,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, } else { // If this is required to be a constant, constant fold it so that we know // that the generated intrinsic gets a ConstantInt. - llvm::APSInt Result; - bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); - assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst; - Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); + Ops.push_back(llvm::ConstantInt::get( + getLLVMContext(), + *E->getArg(i)->getIntegerConstantExpr(getContext()))); } } @@ -7099,9 +7097,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the last argument, which specifies the vector type. assert(HasExtraArg); - llvm::APSInt Result; const Expr *Arg = E->getArg(E->getNumArgs()-1); - if (!Arg->isIntegerConstantExpr(Result, getContext())) + Optional Result = Arg->getIntegerConstantExpr(getContext()); + if (!Result) return nullptr; if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f || @@ -7114,7 +7112,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, Ty = DoubleTy; // Determine whether this is an unsigned conversion or not. - bool usgn = Result.getZExtValue() == 1; + bool usgn = Result->getZExtValue() == 1; unsigned Int = usgn ? Intrinsic::arm_vcvtru : Intrinsic::arm_vcvtr; // Call the appropriate intrinsic. @@ -7123,7 +7121,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, } // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type(Result.getZExtValue()); + NeonTypeFlags Type = Result->getZExtValue(); bool usgn = Type.isUnsigned(); bool rightShift = false; @@ -7267,11 +7265,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, template static Integer GetIntegerConstantValue(const Expr *E, ASTContext &Context) { - llvm::APSInt IntVal; - bool IsConst = E->isIntegerConstantExpr(IntVal, Context); - assert(IsConst && "Sema should have checked this was a constant"); - (void)IsConst; - return IntVal.getExtValue(); + return E->getIntegerConstantExpr(Context)->getExtValue(); } static llvm::Value *SignOrZeroExtend(CGBuilderTy &Builder, llvm::Value *V, @@ -7544,13 +7538,13 @@ static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID assert(E->getNumArgs() >= 3); // Get the last argument, which specifies the vector type. - llvm::APSInt Result; const Expr *Arg = E->getArg(E->getNumArgs() - 1); - if (!Arg->isIntegerConstantExpr(Result, CGF.getContext())) + Optional Result = Arg->getIntegerConstantExpr(CGF.getContext()); + if (!Result) return nullptr; // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type(Result.getZExtValue()); + NeonTypeFlags Type = Result->getZExtValue(); llvm::VectorType *Ty = GetNeonType(&CGF, Type); if (!Ty) return nullptr; @@ -8936,11 +8930,9 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, } else { // If this is required to be a constant, constant fold it so that we know // that the generated intrinsic gets a ConstantInt. - llvm::APSInt Result; - bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); - assert(IsConst && "Constant arg isn't actually constant?"); - (void)IsConst; - Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); + Ops.push_back(llvm::ConstantInt::get( + getLLVMContext(), + *E->getArg(i)->getIntegerConstantExpr(getContext()))); } } @@ -8955,12 +8947,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, return Result; } - llvm::APSInt Result; const Expr *Arg = E->getArg(E->getNumArgs()-1); NeonTypeFlags Type(0); - if (Arg->isIntegerConstantExpr(Result, getContext())) + if (Optional Result = Arg->getIntegerConstantExpr(getContext())) // Determine the type of this overloaded NEON intrinsic. - Type = NeonTypeFlags(Result.getZExtValue()); + Type = NeonTypeFlags(Result->getZExtValue()); bool usgn = Type.isUnsigned(); bool quad = Type.isQuad(); @@ -11791,10 +11782,8 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, // If this is required to be a constant, constant fold it so that we know // that the generated intrinsic gets a ConstantInt. - llvm::APSInt Result; - bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); - assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst; - Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); + Ops.push_back(llvm::ConstantInt::get( + getLLVMContext(), *E->getArg(i)->getIntegerConstantExpr(getContext()))); } // These exist so that the builtin that takes an immediate can be bounds @@ -15073,11 +15062,8 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, llvm::Type *ResultType = ConvertType(E->getType()); Value *X = EmitScalarExpr(E->getArg(0)); // Constant-fold the M4 and M5 mask arguments. - llvm::APSInt M4, M5; - bool IsConstM4 = E->getArg(1)->isIntegerConstantExpr(M4, getContext()); - bool IsConstM5 = E->getArg(2)->isIntegerConstantExpr(M5, getContext()); - assert(IsConstM4 && IsConstM5 && "Constant arg isn't actually constant?"); - (void)IsConstM4; (void)IsConstM5; + llvm::APSInt M4 = *E->getArg(1)->getIntegerConstantExpr(getContext()); + llvm::APSInt M5 = *E->getArg(2)->getIntegerConstantExpr(getContext()); // Check whether this instance can be represented via a LLVM standard // intrinsic. We only support some combinations of M4 and M5. Intrinsic::ID ID = Intrinsic::not_intrinsic; @@ -15132,10 +15118,7 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); // Constant-fold the M4 mask argument. - llvm::APSInt M4; - bool IsConstM4 = E->getArg(2)->isIntegerConstantExpr(M4, getContext()); - assert(IsConstM4 && "Constant arg isn't actually constant?"); - (void)IsConstM4; + llvm::APSInt M4 = *E->getArg(2)->getIntegerConstantExpr(getContext()); // Check whether this instance can be represented via a LLVM standard // intrinsic. We only support some values of M4. Intrinsic::ID ID = Intrinsic::not_intrinsic; @@ -15169,10 +15152,7 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); // Constant-fold the M4 mask argument. - llvm::APSInt M4; - bool IsConstM4 = E->getArg(2)->isIntegerConstantExpr(M4, getContext()); - assert(IsConstM4 && "Constant arg isn't actually constant?"); - (void)IsConstM4; + llvm::APSInt M4 = *E->getArg(2)->getIntegerConstantExpr(getContext()); // Check whether this instance can be represented via a LLVM standard // intrinsic. We only support some values of M4. Intrinsic::ID ID = Intrinsic::not_intrinsic; @@ -15839,10 +15819,11 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Address Dst = EmitPointerWithAlignment(E->getArg(0)); Value *Src = EmitScalarExpr(E->getArg(1)); Value *Ldm = EmitScalarExpr(E->getArg(2)); - llvm::APSInt isColMajorArg; - if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext())) + Optional isColMajorArg = + E->getArg(3)->getIntegerConstantExpr(getContext()); + if (!isColMajorArg) return nullptr; - bool isColMajor = isColMajorArg.getSExtValue(); + bool isColMajor = isColMajorArg->getSExtValue(); NVPTXMmaLdstInfo II = getNVPTXMmaLdstInfo(BuiltinID); unsigned IID = isColMajor ? II.IID_col : II.IID_row; if (IID == 0) @@ -15883,10 +15864,11 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Value *Dst = EmitScalarExpr(E->getArg(0)); Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *Ldm = EmitScalarExpr(E->getArg(2)); - llvm::APSInt isColMajorArg; - if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext())) + Optional isColMajorArg = + E->getArg(3)->getIntegerConstantExpr(getContext()); + if (!isColMajorArg) return nullptr; - bool isColMajor = isColMajorArg.getSExtValue(); + bool isColMajor = isColMajorArg->getSExtValue(); NVPTXMmaLdstInfo II = getNVPTXMmaLdstInfo(BuiltinID); unsigned IID = isColMajor ? II.IID_col : II.IID_row; if (IID == 0) @@ -15933,16 +15915,20 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Address SrcA = EmitPointerWithAlignment(E->getArg(1)); Address SrcB = EmitPointerWithAlignment(E->getArg(2)); Address SrcC = EmitPointerWithAlignment(E->getArg(3)); - llvm::APSInt LayoutArg; - if (!E->getArg(4)->isIntegerConstantExpr(LayoutArg, getContext())) + Optional LayoutArg = + E->getArg(4)->getIntegerConstantExpr(getContext()); + if (!LayoutArg) return nullptr; - int Layout = LayoutArg.getSExtValue(); + int Layout = LayoutArg->getSExtValue(); if (Layout < 0 || Layout > 3) return nullptr; llvm::APSInt SatfArg; if (BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1) SatfArg = 0; // .b1 does not have satf argument. - else if (!E->getArg(5)->isIntegerConstantExpr(SatfArg, getContext())) + else if (Optional OptSatfArg = + E->getArg(5)->getIntegerConstantExpr(getContext())) + SatfArg = *OptSatfArg; + else return nullptr; bool Satf = SatfArg.getSExtValue(); NVPTXMmaInfo MI = getNVPTXMmaInfo(BuiltinID); @@ -16271,9 +16257,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, case WebAssembly::BI__builtin_wasm_extract_lane_i64x2: case WebAssembly::BI__builtin_wasm_extract_lane_f32x4: case WebAssembly::BI__builtin_wasm_extract_lane_f64x2: { - llvm::APSInt LaneConst; - if (!E->getArg(1)->isIntegerConstantExpr(LaneConst, getContext())) - llvm_unreachable("Constant arg isn't actually constant?"); + llvm::APSInt LaneConst = + *E->getArg(1)->getIntegerConstantExpr(getContext()); Value *Vec = EmitScalarExpr(E->getArg(0)); Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst); Value *Extract = Builder.CreateExtractElement(Vec, Lane); @@ -16299,9 +16284,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, case WebAssembly::BI__builtin_wasm_replace_lane_i64x2: case WebAssembly::BI__builtin_wasm_replace_lane_f32x4: case WebAssembly::BI__builtin_wasm_replace_lane_f64x2: { - llvm::APSInt LaneConst; - if (!E->getArg(1)->isIntegerConstantExpr(LaneConst, getContext())) - llvm_unreachable("Constant arg isn't actually constant?"); + llvm::APSInt LaneConst = + *E->getArg(1)->getIntegerConstantExpr(getContext()); Value *Vec = EmitScalarExpr(E->getArg(0)); Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst); Value *Val = EmitScalarExpr(E->getArg(2)); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 9e8770573d701..ab29e32929ceb 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3868,15 +3868,17 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, llvm::APSInt ConstLength; if (Length) { // Idx = LowerBound + Length - 1; - if (Length->isIntegerConstantExpr(ConstLength, C)) { - ConstLength = ConstLength.zextOrTrunc(PointerWidthInBits); + if (Optional CL = Length->getIntegerConstantExpr(C)) { + ConstLength = CL->zextOrTrunc(PointerWidthInBits); Length = nullptr; } auto *LowerBound = E->getLowerBound(); llvm::APSInt ConstLowerBound(PointerWidthInBits, /*isUnsigned=*/false); - if (LowerBound && LowerBound->isIntegerConstantExpr(ConstLowerBound, C)) { - ConstLowerBound = ConstLowerBound.zextOrTrunc(PointerWidthInBits); - LowerBound = nullptr; + if (LowerBound) { + if (Optional LB = LowerBound->getIntegerConstantExpr(C)) { + ConstLowerBound = LB->zextOrTrunc(PointerWidthInBits); + LowerBound = nullptr; + } } if (!Length) --ConstLength; @@ -3913,8 +3915,10 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, : BaseTy; if (auto *VAT = C.getAsVariableArrayType(ArrayTy)) { Length = VAT->getSizeExpr(); - if (Length->isIntegerConstantExpr(ConstLength, C)) + if (Optional L = Length->getIntegerConstantExpr(C)) { + ConstLength = *L; Length = nullptr; + } } else { auto *CAT = C.getAsConstantArrayType(ArrayTy); ConstLength = CAT->getSize(); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index b354e810974c4..f9785e4bea5e2 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -300,20 +300,18 @@ void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, // If specified then alignment must be a "small" power of two. unsigned AlignmentVal = 0; if (Alignment) { - llvm::APSInt Val; + Optional Val; // pack(0) is like pack(), which just works out since that is what // we use 0 for in PackAttr. - if (Alignment->isTypeDependent() || - Alignment->isValueDependent() || - !Alignment->isIntegerConstantExpr(Val, Context) || - !(Val == 0 || Val.isPowerOf2()) || - Val.getZExtValue() > 16) { + if (Alignment->isTypeDependent() || Alignment->isValueDependent() || + !(Val = Alignment->getIntegerConstantExpr(Context)) || + !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) { Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); return; // Ignore } - AlignmentVal = (unsigned) Val.getZExtValue(); + AlignmentVal = (unsigned)Val->getZExtValue(); } if (Action == Sema::PSK_Show) { // Show the current alignment, making sure to show the right value diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index efaf36a693061..c501c706a97bc 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2284,10 +2284,7 @@ bool Sema::CheckARMCoprocessorImmediate(const TargetInfo &TI, if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent()) return false; - llvm::APSInt CoprocNoAP; - bool IsICE = CoprocArg->isIntegerConstantExpr(CoprocNoAP, Context); - (void)IsICE; - assert(IsICE && "Coprocossor immediate is not a constant expression"); + llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context); int64_t CoprocNo = CoprocNoAP.getExtValue(); assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative"); @@ -2599,8 +2596,7 @@ bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID, // The second argument needs to be a constant int Arg = TheCall->getArg(1); - llvm::APSInt Value; - if (!Arg->isIntegerConstantExpr(Value, Context)) { + if (!Arg->isIntegerConstantExpr(Context)) { Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_const) << 2 << Arg->getSourceRange(); return true; @@ -3198,11 +3194,10 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (BuiltinID == SystemZ::BI__builtin_tabort) { Expr *Arg = TheCall->getArg(0); - llvm::APSInt AbortCode(32); - if (Arg->isIntegerConstantExpr(AbortCode, Context) && - AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256) - return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code) - << Arg->getSourceRange(); + if (Optional AbortCode = Arg->getIntegerConstantExpr(Context)) + if (AbortCode->getSExtValue() >= 0 && AbortCode->getSExtValue() < 256) + return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code) + << Arg->getSourceRange(); } // For intrinsics which take an immediate value as part of the instruction, @@ -4923,21 +4918,21 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, } if (SubExprs.size() >= 2 && Form != Init) { - llvm::APSInt Result(32); - if (SubExprs[1]->isIntegerConstantExpr(Result, Context) && - !isValidOrderingForOp(Result.getSExtValue(), Op)) - Diag(SubExprs[1]->getBeginLoc(), - diag::warn_atomic_op_has_invalid_memory_order) - << SubExprs[1]->getSourceRange(); + if (Optional Result = + SubExprs[1]->getIntegerConstantExpr(Context)) + if (!isValidOrderingForOp(Result->getSExtValue(), Op)) + Diag(SubExprs[1]->getBeginLoc(), + diag::warn_atomic_op_has_invalid_memory_order) + << SubExprs[1]->getSourceRange(); } if (auto ScopeModel = AtomicExpr::getScopeModel(Op)) { auto *Scope = Args[Args.size() - 1]; - llvm::APSInt Result(32); - if (Scope->isIntegerConstantExpr(Result, Context) && - !ScopeModel->isValid(Result.getZExtValue())) { - Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope) - << Scope->getSourceRange(); + if (Optional Result = + Scope->getIntegerConstantExpr(Context)) { + if (!ScopeModel->isValid(Result->getZExtValue())) + Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope) + << Scope->getSourceRange(); } SubExprs.push_back(Scope); } @@ -5805,8 +5800,7 @@ bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { << TheCall->getSourceRange(); // Check the third argument is a compile time constant - llvm::APSInt Value; - if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) + if (!TheCall->getArg(2)->isIntegerConstantExpr(Context)) return Diag(TheCall->getBeginLoc(), diag::err_vsx_builtin_nonconstant_argument) << 3 /* argument index */ << TheCall->getDirectCallee() @@ -5901,17 +5895,18 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { TheCall->getArg(i)->isValueDependent()) continue; - llvm::APSInt Result(32); - if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) + Optional Result; + if (!(Result = TheCall->getArg(i)->getIntegerConstantExpr(Context))) return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_nonconstant_argument) << TheCall->getArg(i)->getSourceRange()); // Allow -1 which will be translated to undef in the IR. - if (Result.isSigned() && Result.isAllOnesValue()) + if (Result->isSigned() && Result->isAllOnesValue()) continue; - if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) + if (Result->getActiveBits() > 64 || + Result->getZExtValue() >= numElements * 2) return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_argument_too_large) << TheCall->getArg(i)->getSourceRange()); @@ -6158,10 +6153,11 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, if (Arg->isTypeDependent() || Arg->isValueDependent()) return false; - if (!Arg->isIntegerConstantExpr(Result, Context)) + Optional R; + if (!(R = Arg->getIntegerConstantExpr(Context))) return Diag(TheCall->getBeginLoc(), diag::err_constant_integer_arg_type) << FDecl->getDeclName() << Arg->getSourceRange(); - + Result = *R; return false; } @@ -10321,14 +10317,15 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, // If the shift amount is a positive constant, drop the width by // that much. - llvm::APSInt shift; - if (BO->getRHS()->isIntegerConstantExpr(shift, C) && - shift.isNonNegative()) { - unsigned zext = shift.getZExtValue(); - if (zext >= L.Width) - L.Width = (L.NonNegative ? 0 : 1); - else - L.Width -= zext; + if (Optional shift = + BO->getRHS()->getIntegerConstantExpr(C)) { + if (shift->isNonNegative()) { + unsigned zext = shift->getZExtValue(); + if (zext >= L.Width) + L.Width = (L.NonNegative ? 0 : 1); + else + L.Width -= zext; + } } return L; @@ -10352,9 +10349,9 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext); // If the divisor is constant, use that. - llvm::APSInt divisor; - if (BO->getRHS()->isIntegerConstantExpr(divisor, C)) { - unsigned log2 = divisor.logBase2(); // floor(log_2(divisor)) + if (Optional divisor = + BO->getRHS()->getIntegerConstantExpr(C)) { + unsigned log2 = divisor->logBase2(); // floor(log_2(divisor)) if (log2 >= L.Width) L.Width = (L.NonNegative ? 0 : 1); else @@ -10786,23 +10783,20 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { Expr *RHS = E->getRHS(); if (T->isIntegralType(S.Context)) { - llvm::APSInt RHSValue; - llvm::APSInt LHSValue; - - bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(RHSValue, S.Context); - bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(LHSValue, S.Context); + Optional RHSValue = RHS->getIntegerConstantExpr(S.Context); + Optional LHSValue = LHS->getIntegerConstantExpr(S.Context); // We don't care about expressions whose result is a constant. - if (IsRHSIntegralLiteral && IsLHSIntegralLiteral) + if (RHSValue && LHSValue) return AnalyzeImpConvsInComparison(S, E); // We only care about expressions where just one side is literal - if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) { + if ((bool)RHSValue ^ (bool)LHSValue) { // Is the constant on the RHS or LHS? - const bool RhsConstant = IsRHSIntegralLiteral; + const bool RhsConstant = (bool)RHSValue; Expr *Const = RhsConstant ? RHS : LHS; Expr *Other = RhsConstant ? LHS : RHS; - const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue; + const llvm::APSInt &Value = RhsConstant ? *RHSValue : *LHSValue; // Check whether an integer constant comparison results in a value // of 'true' or 'false'. @@ -11760,8 +11754,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (SourcePrecision > 0 && TargetPrecision > 0 && SourcePrecision > TargetPrecision) { - llvm::APSInt SourceInt; - if (E->isIntegerConstantExpr(SourceInt, S.Context)) { + if (Optional SourceInt = + E->getIntegerConstantExpr(S.Context)) { // If the source integer is a constant, convert it to the target // floating point type. Issue a warning if the value changes // during the whole conversion. @@ -11769,11 +11763,11 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, S.Context.getFloatTypeSemantics(QualType(TargetBT, 0))); llvm::APFloat::opStatus ConversionStatus = TargetFloatValue.convertFromAPInt( - SourceInt, SourceBT->isSignedInteger(), + *SourceInt, SourceBT->isSignedInteger(), llvm::APFloat::rmNearestTiesToEven); if (ConversionStatus != llvm::APFloat::opOK) { - std::string PrettySourceValue = SourceInt.toString(10); + std::string PrettySourceValue = SourceInt->toString(10); SmallString<32> PrettyTargetValue; TargetFloatValue.toString(PrettyTargetValue, TargetPrecision); @@ -14124,9 +14118,10 @@ namespace { return; if (Expr *RHS = BinOp->getRHS()) { RHS = RHS->IgnoreParenCasts(); - llvm::APSInt Value; + Optional Value; VarWillBeReased = - (RHS && RHS->isIntegerConstantExpr(Value, Context) && Value == 0); + (RHS && (Value = RHS->getIntegerConstantExpr(Context)) && + *Value == 0); } } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f5e375134c293..dc0f3d68fde38 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13141,20 +13141,20 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { if (!MagicValueExpr) { continue; } - llvm::APSInt MagicValueInt; - if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) { + Optional MagicValueInt; + if (!(MagicValueInt = MagicValueExpr->getIntegerConstantExpr(Context))) { Diag(I->getRange().getBegin(), diag::err_type_tag_for_datatype_not_ice) << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); continue; } - if (MagicValueInt.getActiveBits() > 64) { + if (MagicValueInt->getActiveBits() > 64) { Diag(I->getRange().getBegin(), diag::err_type_tag_for_datatype_too_large) << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); continue; } - uint64_t MagicValue = MagicValueInt.getZExtValue(); + uint64_t MagicValue = MagicValueInt->getZExtValue(); RegisterTypeTagForDatatype(I->getArgumentKind(), MagicValue, I->getMatchingCType(), diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 1a0594512a606..ece93cbd6a9bd 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -240,9 +240,9 @@ template static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx = UINT_MAX, bool StrictlyUnsigned = false) { - llvm::APSInt I(32); + Optional I = llvm::APSInt(32); if (Expr->isTypeDependent() || Expr->isValueDependent() || - !Expr->isIntegerConstantExpr(I, S.Context)) { + !(I = Expr->getIntegerConstantExpr(S.Context))) { if (Idx != UINT_MAX) S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) << &AI << Idx << AANT_ArgumentIntegerConstant @@ -253,19 +253,19 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, return false; } - if (!I.isIntN(32)) { + if (!I->isIntN(32)) { S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) - << I.toString(10, false) << 32 << /* Unsigned */ 1; + << I->toString(10, false) << 32 << /* Unsigned */ 1; return false; } - if (StrictlyUnsigned && I.isSigned() && I.isNegative()) { + if (StrictlyUnsigned && I->isSigned() && I->isNegative()) { S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer) << &AI << /*non-negative*/ 1; return false; } - Val = (uint32_t)I.getZExtValue(); + Val = (uint32_t)I->getZExtValue(); return true; } @@ -332,16 +332,16 @@ static bool checkFunctionOrMethodParameterIndex( unsigned NumParams = (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam; - llvm::APSInt IdxInt; + Optional IdxInt; if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || - !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { + !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) << &AI << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange(); return false; } - unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX); + unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX); if (IdxSource < 1 || (!IV && IdxSource > NumParams)) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds) << &AI << AttrArgNum << IdxExpr->getSourceRange(); @@ -1605,8 +1605,8 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, } if (!E->isValueDependent()) { - llvm::APSInt I(64); - if (!E->isIntegerConstantExpr(I, Context)) { + Optional I = llvm::APSInt(64); + if (!(I = E->getIntegerConstantExpr(Context))) { if (OE) Diag(AttrLoc, diag::err_attribute_argument_n_type) << &TmpAttr << 1 << AANT_ArgumentIntegerConstant @@ -1618,27 +1618,22 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, return; } - if (!I.isPowerOf2()) { + if (!I->isPowerOf2()) { Diag(AttrLoc, diag::err_alignment_not_power_of_two) << E->getSourceRange(); return; } - if (I > Sema::MaximumAlignment) + if (*I > Sema::MaximumAlignment) Diag(CI.getLoc(), diag::warn_assume_aligned_too_great) << CI.getRange() << Sema::MaximumAlignment; } - if (OE) { - if (!OE->isValueDependent()) { - llvm::APSInt I(64); - if (!OE->isIntegerConstantExpr(I, Context)) { - Diag(AttrLoc, diag::err_attribute_argument_n_type) - << &TmpAttr << 2 << AANT_ArgumentIntegerConstant - << OE->getSourceRange(); - return; - } - } + if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) { + Diag(AttrLoc, diag::err_attribute_argument_n_type) + << &TmpAttr << 2 << AANT_ArgumentIntegerConstant + << OE->getSourceRange(); + return; } D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE)); @@ -2729,36 +2724,36 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel; if (AL.getNumArgs() > 0) { Expr *E = AL.getArgAsExpr(0); - llvm::APSInt Idx(32); + Optional Idx = llvm::APSInt(32); if (E->isTypeDependent() || E->isValueDependent() || - !E->isIntegerConstantExpr(Idx, S.Context)) { + !(Idx = E->getIntegerConstantExpr(S.Context))) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange(); return; } - if (Idx.isSigned() && Idx.isNegative()) { + if (Idx->isSigned() && Idx->isNegative()) { S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero) << E->getSourceRange(); return; } - sentinel = Idx.getZExtValue(); + sentinel = Idx->getZExtValue(); } unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos; if (AL.getNumArgs() > 1) { Expr *E = AL.getArgAsExpr(1); - llvm::APSInt Idx(32); + Optional Idx = llvm::APSInt(32); if (E->isTypeDependent() || E->isValueDependent() || - !E->isIntegerConstantExpr(Idx, S.Context)) { + !(Idx = E->getIntegerConstantExpr(S.Context))) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange(); return; } - nullPos = Idx.getZExtValue(); + nullPos = Idx->getZExtValue(); - if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) { + if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) { // FIXME: This error message could be improved, it would be nice // to say what the bounds actually are. S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) @@ -4833,19 +4828,19 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E, if (E->isValueDependent()) return E; - llvm::APSInt I(64); - if (!E->isIntegerConstantExpr(I, S.Context)) { + Optional I = llvm::APSInt(64); + if (!(I = E->getIntegerConstantExpr(S.Context))) { S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); return nullptr; } // Make sure we can fit it in 32 bits. - if (!I.isIntN(32)) { - S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false) - << 32 << /* Unsigned */ 1; + if (!I->isIntN(32)) { + S.Diag(E->getExprLoc(), diag::err_ice_too_large) + << I->toString(10, false) << 32 << /* Unsigned */ 1; return nullptr; } - if (I < 0) + if (*I < 0) S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) << &AL << Idx << E->getSourceRange(); @@ -5686,18 +5681,18 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } Expr *NumParamsExpr = static_cast(AL.getArgAsExpr(0)); - llvm::APSInt NumParams(32); - if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { + Optional NumParams = llvm::APSInt(32); + if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(S.Context))) { S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL << AANT_ArgumentIntegerConstant << NumParamsExpr->getSourceRange(); return; } // The argument should be in range 0..63. - unsigned Num = NumParams.getLimitedValue(255); + unsigned Num = NumParams->getLimitedValue(255); if (Num > 63) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) - << AL << (int)NumParams.getSExtValue() + << AL << (int)NumParams->getSExtValue() << NumParamsExpr->getSourceRange(); return; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d885920b6c14e..e3aa817c62249 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2073,29 +2073,29 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // per CWG1464. Otherwise, if it's not a constant, we must have an // unparenthesized array type. if (!(*ArraySize)->isValueDependent()) { - llvm::APSInt Value; // We've already performed any required implicit conversion to integer or // unscoped enumeration type. // FIXME: Per CWG1464, we are required to check the value prior to // converting to size_t. This will never find a negative array size in // C++14 onwards, because Value is always unsigned here! - if ((*ArraySize)->isIntegerConstantExpr(Value, Context)) { - if (Value.isSigned() && Value.isNegative()) { + if (Optional Value = + (*ArraySize)->getIntegerConstantExpr(Context)) { + if (Value->isSigned() && Value->isNegative()) { return ExprError(Diag((*ArraySize)->getBeginLoc(), diag::err_typecheck_negative_array_size) << (*ArraySize)->getSourceRange()); } if (!AllocType->isDependentType()) { - unsigned ActiveSizeBits = - ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); + unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits( + Context, AllocType, *Value); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) return ExprError( Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large) - << Value.toString(10) << (*ArraySize)->getSourceRange()); + << Value->toString(10) << (*ArraySize)->getSourceRange()); } - KnownArraySize = Value.getZExtValue(); + KnownArraySize = Value->getZExtValue(); } else if (TypeIdParens.isValid()) { // Can't have dynamic array size when the type-id is in parentheses. Diag((*ArraySize)->getBeginLoc(), diag::ext_new_paren_array_nonconst) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index b27abb54c170f..d1ddf10724172 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5989,8 +5989,7 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, // Deal with non-constant score and user condition expressions. auto HandleNonConstantScoresAndConditions = [this](Expr *&E, bool IsScore) -> bool { - llvm::APSInt Result; - if (!E || E->isIntegerConstantExpr(Result, Context)) + if (!E || E->isIntegerConstantExpr(Context)) return false; if (IsScore) { @@ -6476,14 +6475,14 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { // loop. If test-expr is of form b relational-op var and relational-op is // > or >= then incr-expr must cause var to increase on each iteration of // the loop. - llvm::APSInt Result; - bool IsConstant = NewStep->isIntegerConstantExpr(Result, SemaRef.Context); + Optional Result = + NewStep->getIntegerConstantExpr(SemaRef.Context); bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation(); bool IsConstNeg = - IsConstant && Result.isSigned() && (Subtract != Result.isNegative()); + Result && Result->isSigned() && (Subtract != Result->isNegative()); bool IsConstPos = - IsConstant && Result.isSigned() && (Subtract == Result.isNegative()); - bool IsConstZero = IsConstant && !Result.getBoolValue(); + Result && Result->isSigned() && (Subtract == Result->isNegative()); + bool IsConstZero = Result && !Result->getBoolValue(); // != with increment is treated as <; != with decrement is treated as > if (!TestIsLessOp.hasValue()) @@ -7914,9 +7913,9 @@ static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) { static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) { if (E == nullptr) return false; - llvm::APSInt Result; - if (E->isIntegerConstantExpr(Result, SemaRef.Context)) - return Signed ? Result.isSignedIntN(Bits) : Result.isIntN(Bits); + if (Optional Result = + E->getIntegerConstantExpr(SemaRef.Context)) + return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits); return false; } @@ -8189,9 +8188,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Calculate the last iteration number beforehand instead of doing this on // each iteration. Do not do this if the number of iterations may be kfold-ed. - llvm::APSInt Result; - bool IsConstant = - LastIteration.get()->isIntegerConstantExpr(Result, SemaRef.Context); + bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context); ExprResult CalcLastIteration; if (!IsConstant) { ExprResult SaveRef = @@ -12582,15 +12579,16 @@ isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, ValExpr = Value.get(); // The expression must evaluate to a non-negative integer value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) && - Result.isSigned() && - !((!StrictlyPositive && Result.isNonNegative()) || - (StrictlyPositive && Result.isStrictlyPositive()))) { - SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) - << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) - << ValExpr->getSourceRange(); - return false; + if (Optional Result = + ValExpr->getIntegerConstantExpr(SemaRef.Context)) { + if (Result->isSigned() && + !((!StrictlyPositive && Result->isNonNegative()) || + (StrictlyPositive && Result->isStrictlyPositive()))) { + SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) + << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) + << ValExpr->getSourceRange(); + return false; + } } if (!BuildCapture) return true; @@ -13215,9 +13213,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, Context)) { - if (Result.isSigned() && !Result.isStrictlyPositive()) { + if (Optional Result = + ValExpr->getIntegerConstantExpr(Context)) { + if (Result->isSigned() && !Result->isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) << "schedule" << 1 << ChunkSize->getSourceRange(); return nullptr; @@ -15688,12 +15686,12 @@ OMPClause *Sema::ActOnOpenMPLinearClause( // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). - llvm::APSInt Result; - bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context); - if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive()) - Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0] - << (Vars.size() > 1); - if (!IsConstant && CalcStep.isUsable()) { + if (Optional Result = + StepExpr->getIntegerConstantExpr(Context)) { + if (!Result->isNegative() && !Result->isStrictlyPositive()) + Diag(StepLoc, diag::warn_omp_linear_step_zero) + << Vars[0] << (Vars.size() > 1); + } else if (CalcStep.isUsable()) { // Calculate the step beforehand instead of doing this on each iteration. // (This is not used if the number of iterations may be kfold-ed). CalcStepExpr = CalcStep.get(); @@ -18225,9 +18223,9 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - llvm::APSInt Result; - if (ValExpr->isIntegerConstantExpr(Result, Context)) { - if (Result.isSigned() && !Result.isStrictlyPositive()) { + if (Optional Result = + ValExpr->getIntegerConstantExpr(Context)) { + if (Result->isSigned() && !Result->isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) << "dist_schedule" << ChunkSize->getSourceRange(); return nullptr; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 8635397f48067..7c6acf011d574 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -346,7 +346,6 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( ToType->isRealFloatingType()) { if (IgnoreFloatToIntegralConversion) return NK_Not_Narrowing; - llvm::APSInt IntConstantValue; const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); assert(Initializer && "Unknown conversion expression"); @@ -354,19 +353,20 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( if (Initializer->isValueDependent()) return NK_Dependent_Narrowing; - if (Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { + if (Optional IntConstantValue = + Initializer->getIntegerConstantExpr(Ctx)) { // Convert the integer to the floating type. llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType)); - Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(), + Result.convertFromAPInt(*IntConstantValue, IntConstantValue->isSigned(), llvm::APFloat::rmNearestTiesToEven); // And back. - llvm::APSInt ConvertedValue = IntConstantValue; + llvm::APSInt ConvertedValue = *IntConstantValue; bool ignored; Result.convertToInteger(ConvertedValue, llvm::APFloat::rmTowardZero, &ignored); // If the resulting value is different, this was a narrowing conversion. - if (IntConstantValue != ConvertedValue) { - ConstantValue = APValue(IntConstantValue); + if (*IntConstantValue != ConvertedValue) { + ConstantValue = APValue(*IntConstantValue); ConstantType = Initializer->getType(); return NK_Constant_Narrowing; } @@ -430,17 +430,18 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( (FromWidth == ToWidth && FromSigned != ToSigned) || (FromSigned && !ToSigned)) { // Not all values of FromType can be represented in ToType. - llvm::APSInt InitializerValue; const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); // If it's value-dependent, we can't tell whether it's narrowing. if (Initializer->isValueDependent()) return NK_Dependent_Narrowing; - if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { + Optional OptInitializerValue; + if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) { // Such conversions on variables are always narrowing. return NK_Variable_Narrowing; } + llvm::APSInt &InitializerValue = *OptInitializerValue; bool Narrowing = false; if (FromWidth < ToWidth) { // Negative -> unsigned is narrowing. Otherwise, more bits is never @@ -2183,21 +2184,22 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // compatibility. if (From) { if (FieldDecl *MemberDecl = From->getSourceBitField()) { - llvm::APSInt BitWidth; + Optional BitWidth; if (FromType->isIntegralType(Context) && - MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { - llvm::APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); + (BitWidth = + MemberDecl->getBitWidth()->getIntegerConstantExpr(Context))) { + llvm::APSInt ToSize(BitWidth->getBitWidth(), BitWidth->isUnsigned()); ToSize = Context.getTypeSize(ToType); // Are we promoting to an int from a bitfield that fits in an int? - if (BitWidth < ToSize || - (FromType->isSignedIntegerType() && BitWidth <= ToSize)) { + if (*BitWidth < ToSize || + (FromType->isSignedIntegerType() && *BitWidth <= ToSize)) { return To->getKind() == BuiltinType::Int; } // Are we promoting to an unsigned int from an unsigned bitfield // that fits into an unsigned int? - if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) { + if (FromType->isUnsignedIntegerType() && *BitWidth <= ToSize) { return To->getKind() == BuiltinType::UInt; } diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index e9d3c755eb232..c7b97ec4d975a 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -335,15 +335,15 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, if (NumArgs == 1) { Expr *E = A.getArgAsExpr(0); - llvm::APSInt ArgVal(32); + Optional ArgVal; - if (!E->isIntegerConstantExpr(ArgVal, S.Context)) { + if (!(ArgVal = E->getIntegerConstantExpr(S.Context))) { S.Diag(A.getLoc(), diag::err_attribute_argument_type) << A << AANT_ArgumentIntegerConstant << E->getSourceRange(); return nullptr; } - int Val = ArgVal.getSExtValue(); + int Val = ArgVal->getSExtValue(); if (Val <= 0) { S.Diag(A.getRange().getBegin(), diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index b8f7f1a581590..13426cbf2db40 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2476,8 +2476,8 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, VectorType::GenericVector); - llvm::APSInt VecSize(32); - if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) { + Optional VecSize = SizeExpr->getIntegerConstantExpr(Context); + if (!VecSize) { Diag(AttrLoc, diag::err_attribute_argument_type) << "vector_size" << AANT_ArgumentIntegerConstant << SizeExpr->getSourceRange(); @@ -2489,13 +2489,13 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, VectorType::GenericVector); // vecSize is specified in bytes - convert to bits. - if (!VecSize.isIntN(61)) { + if (!VecSize->isIntN(61)) { // Bit size will overflow uint64. Diag(AttrLoc, diag::err_attribute_size_too_large) << SizeExpr->getSourceRange() << "vector"; return QualType(); } - uint64_t VectorSizeBits = VecSize.getZExtValue() * 8; + uint64_t VectorSizeBits = VecSize->getZExtValue() * 8; unsigned TypeSize = static_cast(Context.getTypeSize(CurType)); if (VectorSizeBits == 0) { @@ -2540,8 +2540,8 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, } if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) { - llvm::APSInt vecSize(32); - if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) { + Optional vecSize = ArraySize->getIntegerConstantExpr(Context); + if (!vecSize) { Diag(AttrLoc, diag::err_attribute_argument_type) << "ext_vector_type" << AANT_ArgumentIntegerConstant << ArraySize->getSourceRange(); @@ -2555,7 +2555,7 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, } // Unlike gcc's vector_size attribute, the size is specified as the // number of elements, not the number of bytes. - unsigned vectorSize = static_cast(vecSize.getZExtValue()); + unsigned vectorSize = static_cast(vecSize->getZExtValue()); if (vectorSize == 0) { Diag(AttrLoc, diag::err_attribute_zero_size) @@ -6254,13 +6254,15 @@ static bool BuildAddressSpaceIndex(Sema &S, LangAS &ASIdx, const Expr *AddrSpace, SourceLocation AttrLoc) { if (!AddrSpace->isValueDependent()) { - llvm::APSInt addrSpace(32); - if (!AddrSpace->isIntegerConstantExpr(addrSpace, S.Context)) { + Optional OptAddrSpace = + AddrSpace->getIntegerConstantExpr(S.Context); + if (!OptAddrSpace) { S.Diag(AttrLoc, diag::err_attribute_argument_type) << "'address_space'" << AANT_ArgumentIntegerConstant << AddrSpace->getSourceRange(); return false; } + llvm::APSInt &addrSpace = *OptAddrSpace; // Bounds checking. if (addrSpace.isSigned()) { @@ -7712,9 +7714,9 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, } // The number of elements must be an ICE. Expr *numEltsExpr = static_cast(Attr.getArgAsExpr(0)); - llvm::APSInt numEltsInt(32); + Optional numEltsInt; if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() || - !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) { + !(numEltsInt = numEltsExpr->getIntegerConstantExpr(S.Context))) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr << AANT_ArgumentIntegerConstant << numEltsExpr->getSourceRange(); @@ -7730,7 +7732,7 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, // The total size of the vector must be 64 or 128 bits. unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); - unsigned numElts = static_cast(numEltsInt.getZExtValue()); + unsigned numElts = static_cast(numEltsInt->getZExtValue()); unsigned vecSize = typeSize * numElts; if (vecSize != 64 && vecSize != 128) { S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType; From c94332919bd922032e979b3ae3ced5ca5bdf9650 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Sun, 12 Jul 2020 20:29:19 -0700 Subject: [PATCH 063/771] Revert "Rename/refactor isIntegerConstantExpression to getIntegerConstantExpression" Broke buildbots since I hadn't updated this patch in a while. Sorry for the noise. This reverts commit 49e5f603d40083dce9c05796e3cde3a185c3beba. --- clang/include/clang/AST/Expr.h | 13 ++-- clang/lib/AST/ASTContext.cpp | 16 +++-- clang/lib/AST/ExprConstant.cpp | 19 ++--- clang/lib/AST/MicrosoftMangle.cpp | 6 +- clang/lib/CodeGen/CGBuiltin.cpp | 114 +++++++++++++++++------------- clang/lib/CodeGen/CGExpr.cpp | 16 ++--- clang/lib/Sema/SemaAttr.cpp | 12 ++-- clang/lib/Sema/SemaChecking.cpp | 107 +++++++++++++++------------- clang/lib/Sema/SemaDecl.cpp | 8 +-- clang/lib/Sema/SemaDeclAttr.cpp | 77 ++++++++++---------- clang/lib/Sema/SemaExprCXX.cpp | 14 ++-- clang/lib/Sema/SemaOpenMP.cpp | 66 ++++++++--------- clang/lib/Sema/SemaOverload.cpp | 30 ++++---- clang/lib/Sema/SemaStmtAttr.cpp | 6 +- clang/lib/Sema/SemaType.cpp | 26 ++++--- 15 files changed, 275 insertions(+), 255 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index a42c7bb5a9f26..66eafaaab715e 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -510,15 +510,16 @@ class Expr : public ValueStmt { /// semantically correspond to a bool. bool isKnownToHaveBooleanValue(bool Semantic = true) const; - /// isIntegerConstantExpr - Return the value if this expression is a valid - /// integer constant expression. If not a valid i-c-e, return None and fill - /// in Loc (if specified) with the location of the invalid expression. + /// isIntegerConstantExpr - Return true if this expression is a valid integer + /// constant expression, and, if so, return its value in Result. If not a + /// valid i-c-e, return false and fill in Loc (if specified) with the location + /// of the invalid expression. /// /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. - Optional getIntegerConstantExpr(const ASTContext &Ctx, - SourceLocation *Loc = nullptr, - bool isEvaluated = true) const; + bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx, + SourceLocation *Loc = nullptr, + bool isEvaluated = true) const; bool isIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc = nullptr) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 807028885652d..2ba643f12a82f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -9471,15 +9471,17 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, const ConstantArrayType* CAT) -> std::pair { if (VAT) { - Optional TheInt; + llvm::APSInt TheInt; Expr *E = VAT->getSizeExpr(); - if (E && (TheInt = E->getIntegerConstantExpr(*this))) - return std::make_pair(true, *TheInt); - return std::make_pair(false, llvm::APSInt()); + if (E && E->isIntegerConstantExpr(TheInt, *this)) + return std::make_pair(true, TheInt); + else + return std::make_pair(false, TheInt); + } else if (CAT) { + return std::make_pair(true, CAT->getSize()); + } else { + return std::make_pair(false, llvm::APInt()); } - if (CAT) - return std::make_pair(true, CAT->getSize()); - return std::make_pair(false, llvm::APInt()); }; bool HaveLSize, HaveRSize; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 011dc890496d0..a4dc0ccad1e0f 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -14883,22 +14883,16 @@ bool Expr::isIntegerConstantExpr(const ASTContext &Ctx, return true; } -Optional Expr::getIntegerConstantExpr(const ASTContext &Ctx, - SourceLocation *Loc, - bool isEvaluated) const { +bool Expr::isIntegerConstantExpr(llvm::APSInt &Value, const ASTContext &Ctx, + SourceLocation *Loc, bool isEvaluated) const { assert(!isValueDependent() && "Expression evaluator can't be called on a dependent expression."); - APSInt Value; - - if (Ctx.getLangOpts().CPlusPlus11) { - if (EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc)) - return Value; - return None; - } + if (Ctx.getLangOpts().CPlusPlus11) + return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, &Value, Loc); if (!isIntegerConstantExpr(Ctx, Loc)) - return None; + return false; // The only possible side-effects here are due to UB discovered in the // evaluation (for instance, INT_MAX + 1). In such a case, we are still @@ -14912,7 +14906,8 @@ Optional Expr::getIntegerConstantExpr(const ASTContext &Ctx, if (!::EvaluateAsInt(this, ExprResult, Ctx, SE_AllowSideEffects, Info)) llvm_unreachable("ICE cannot be evaluated!"); - return ExprResult.Val.getInt(); + Value = ExprResult.Val.getInt(); + return true; } bool Expr::isCXX98IntegralConstantExpr(const ASTContext &Ctx) const { diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp index 09579c28061ae..529f301e46964 100644 --- a/clang/lib/AST/MicrosoftMangle.cpp +++ b/clang/lib/AST/MicrosoftMangle.cpp @@ -1372,9 +1372,9 @@ void MicrosoftCXXNameMangler::mangleIntegerLiteral(const llvm::APSInt &Value, void MicrosoftCXXNameMangler::mangleExpression(const Expr *E) { // See if this is a constant expression. - if (Optional Value = - E->getIntegerConstantExpr(Context.getASTContext())) { - mangleIntegerLiteral(*Value, E->getType()->isBooleanType()); + llvm::APSInt Value; + if (E->isIntegerConstantExpr(Value, Context.getASTContext())) { + mangleIntegerLiteral(Value, E->getType()->isBooleanType()); return; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3588e33714d2f..35a93a7889f40 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -4419,9 +4419,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, } else { // If this is required to be a constant, constant fold it so that we // know that the generated intrinsic gets a ConstantInt. - ArgValue = llvm::ConstantInt::get( - getLLVMContext(), - *E->getArg(i)->getIntegerConstantExpr(getContext())); + llvm::APSInt Result; + bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result,getContext()); + assert(IsConst && "Constant arg isn't actually constant?"); + (void)IsConst; + ArgValue = llvm::ConstantInt::get(getLLVMContext(), Result); } // If the intrinsic arg type is different from the builtin arg type @@ -5594,14 +5596,13 @@ Value *CodeGenFunction::EmitCommonNeonBuiltinExpr( SmallVectorImpl &Ops, Address PtrOp0, Address PtrOp1, llvm::Triple::ArchType Arch) { // Get the last argument, which specifies the vector type. + llvm::APSInt NeonTypeConst; const Expr *Arg = E->getArg(E->getNumArgs() - 1); - Optional NeonTypeConst = - Arg->getIntegerConstantExpr(getContext()); - if (!NeonTypeConst) + if (!Arg->isIntegerConstantExpr(NeonTypeConst, getContext())) return nullptr; // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type(NeonTypeConst->getZExtValue()); + NeonTypeFlags Type(NeonTypeConst.getZExtValue()); bool Usgn = Type.isUnsigned(); bool Quad = Type.isQuad(); const bool HasLegalHalfType = getTarget().hasLegalHalfType(); @@ -6884,9 +6885,10 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, } else { // If this is required to be a constant, constant fold it so that we know // that the generated intrinsic gets a ConstantInt. - Ops.push_back(llvm::ConstantInt::get( - getLLVMContext(), - *E->getArg(i)->getIntegerConstantExpr(getContext()))); + llvm::APSInt Result; + bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); + assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst; + Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); } } @@ -7097,9 +7099,9 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, // Get the last argument, which specifies the vector type. assert(HasExtraArg); + llvm::APSInt Result; const Expr *Arg = E->getArg(E->getNumArgs()-1); - Optional Result = Arg->getIntegerConstantExpr(getContext()); - if (!Result) + if (!Arg->isIntegerConstantExpr(Result, getContext())) return nullptr; if (BuiltinID == ARM::BI__builtin_arm_vcvtr_f || @@ -7112,7 +7114,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, Ty = DoubleTy; // Determine whether this is an unsigned conversion or not. - bool usgn = Result->getZExtValue() == 1; + bool usgn = Result.getZExtValue() == 1; unsigned Int = usgn ? Intrinsic::arm_vcvtru : Intrinsic::arm_vcvtr; // Call the appropriate intrinsic. @@ -7121,7 +7123,7 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, } // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type = Result->getZExtValue(); + NeonTypeFlags Type(Result.getZExtValue()); bool usgn = Type.isUnsigned(); bool rightShift = false; @@ -7265,7 +7267,11 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID, template static Integer GetIntegerConstantValue(const Expr *E, ASTContext &Context) { - return E->getIntegerConstantExpr(Context)->getExtValue(); + llvm::APSInt IntVal; + bool IsConst = E->isIntegerConstantExpr(IntVal, Context); + assert(IsConst && "Sema should have checked this was a constant"); + (void)IsConst; + return IntVal.getExtValue(); } static llvm::Value *SignOrZeroExtend(CGBuilderTy &Builder, llvm::Value *V, @@ -7538,13 +7544,13 @@ static Value *EmitAArch64TblBuiltinExpr(CodeGenFunction &CGF, unsigned BuiltinID assert(E->getNumArgs() >= 3); // Get the last argument, which specifies the vector type. + llvm::APSInt Result; const Expr *Arg = E->getArg(E->getNumArgs() - 1); - Optional Result = Arg->getIntegerConstantExpr(CGF.getContext()); - if (!Result) + if (!Arg->isIntegerConstantExpr(Result, CGF.getContext())) return nullptr; // Determine the type of this overloaded NEON intrinsic. - NeonTypeFlags Type = Result->getZExtValue(); + NeonTypeFlags Type(Result.getZExtValue()); llvm::VectorType *Ty = GetNeonType(&CGF, Type); if (!Ty) return nullptr; @@ -8930,9 +8936,11 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, } else { // If this is required to be a constant, constant fold it so that we know // that the generated intrinsic gets a ConstantInt. - Ops.push_back(llvm::ConstantInt::get( - getLLVMContext(), - *E->getArg(i)->getIntegerConstantExpr(getContext()))); + llvm::APSInt Result; + bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); + assert(IsConst && "Constant arg isn't actually constant?"); + (void)IsConst; + Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); } } @@ -8947,11 +8955,12 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, return Result; } + llvm::APSInt Result; const Expr *Arg = E->getArg(E->getNumArgs()-1); NeonTypeFlags Type(0); - if (Optional Result = Arg->getIntegerConstantExpr(getContext())) + if (Arg->isIntegerConstantExpr(Result, getContext())) // Determine the type of this overloaded NEON intrinsic. - Type = NeonTypeFlags(Result->getZExtValue()); + Type = NeonTypeFlags(Result.getZExtValue()); bool usgn = Type.isUnsigned(); bool quad = Type.isQuad(); @@ -11782,8 +11791,10 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, // If this is required to be a constant, constant fold it so that we know // that the generated intrinsic gets a ConstantInt. - Ops.push_back(llvm::ConstantInt::get( - getLLVMContext(), *E->getArg(i)->getIntegerConstantExpr(getContext()))); + llvm::APSInt Result; + bool IsConst = E->getArg(i)->isIntegerConstantExpr(Result, getContext()); + assert(IsConst && "Constant arg isn't actually constant?"); (void)IsConst; + Ops.push_back(llvm::ConstantInt::get(getLLVMContext(), Result)); } // These exist so that the builtin that takes an immediate can be bounds @@ -15062,8 +15073,11 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, llvm::Type *ResultType = ConvertType(E->getType()); Value *X = EmitScalarExpr(E->getArg(0)); // Constant-fold the M4 and M5 mask arguments. - llvm::APSInt M4 = *E->getArg(1)->getIntegerConstantExpr(getContext()); - llvm::APSInt M5 = *E->getArg(2)->getIntegerConstantExpr(getContext()); + llvm::APSInt M4, M5; + bool IsConstM4 = E->getArg(1)->isIntegerConstantExpr(M4, getContext()); + bool IsConstM5 = E->getArg(2)->isIntegerConstantExpr(M5, getContext()); + assert(IsConstM4 && IsConstM5 && "Constant arg isn't actually constant?"); + (void)IsConstM4; (void)IsConstM5; // Check whether this instance can be represented via a LLVM standard // intrinsic. We only support some combinations of M4 and M5. Intrinsic::ID ID = Intrinsic::not_intrinsic; @@ -15118,7 +15132,10 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); // Constant-fold the M4 mask argument. - llvm::APSInt M4 = *E->getArg(2)->getIntegerConstantExpr(getContext()); + llvm::APSInt M4; + bool IsConstM4 = E->getArg(2)->isIntegerConstantExpr(M4, getContext()); + assert(IsConstM4 && "Constant arg isn't actually constant?"); + (void)IsConstM4; // Check whether this instance can be represented via a LLVM standard // intrinsic. We only support some values of M4. Intrinsic::ID ID = Intrinsic::not_intrinsic; @@ -15152,7 +15169,10 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, Value *X = EmitScalarExpr(E->getArg(0)); Value *Y = EmitScalarExpr(E->getArg(1)); // Constant-fold the M4 mask argument. - llvm::APSInt M4 = *E->getArg(2)->getIntegerConstantExpr(getContext()); + llvm::APSInt M4; + bool IsConstM4 = E->getArg(2)->isIntegerConstantExpr(M4, getContext()); + assert(IsConstM4 && "Constant arg isn't actually constant?"); + (void)IsConstM4; // Check whether this instance can be represented via a LLVM standard // intrinsic. We only support some values of M4. Intrinsic::ID ID = Intrinsic::not_intrinsic; @@ -15819,11 +15839,10 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Address Dst = EmitPointerWithAlignment(E->getArg(0)); Value *Src = EmitScalarExpr(E->getArg(1)); Value *Ldm = EmitScalarExpr(E->getArg(2)); - Optional isColMajorArg = - E->getArg(3)->getIntegerConstantExpr(getContext()); - if (!isColMajorArg) + llvm::APSInt isColMajorArg; + if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext())) return nullptr; - bool isColMajor = isColMajorArg->getSExtValue(); + bool isColMajor = isColMajorArg.getSExtValue(); NVPTXMmaLdstInfo II = getNVPTXMmaLdstInfo(BuiltinID); unsigned IID = isColMajor ? II.IID_col : II.IID_row; if (IID == 0) @@ -15864,11 +15883,10 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Value *Dst = EmitScalarExpr(E->getArg(0)); Address Src = EmitPointerWithAlignment(E->getArg(1)); Value *Ldm = EmitScalarExpr(E->getArg(2)); - Optional isColMajorArg = - E->getArg(3)->getIntegerConstantExpr(getContext()); - if (!isColMajorArg) + llvm::APSInt isColMajorArg; + if (!E->getArg(3)->isIntegerConstantExpr(isColMajorArg, getContext())) return nullptr; - bool isColMajor = isColMajorArg->getSExtValue(); + bool isColMajor = isColMajorArg.getSExtValue(); NVPTXMmaLdstInfo II = getNVPTXMmaLdstInfo(BuiltinID); unsigned IID = isColMajor ? II.IID_col : II.IID_row; if (IID == 0) @@ -15915,20 +15933,16 @@ CodeGenFunction::EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E) { Address SrcA = EmitPointerWithAlignment(E->getArg(1)); Address SrcB = EmitPointerWithAlignment(E->getArg(2)); Address SrcC = EmitPointerWithAlignment(E->getArg(3)); - Optional LayoutArg = - E->getArg(4)->getIntegerConstantExpr(getContext()); - if (!LayoutArg) + llvm::APSInt LayoutArg; + if (!E->getArg(4)->isIntegerConstantExpr(LayoutArg, getContext())) return nullptr; - int Layout = LayoutArg->getSExtValue(); + int Layout = LayoutArg.getSExtValue(); if (Layout < 0 || Layout > 3) return nullptr; llvm::APSInt SatfArg; if (BuiltinID == NVPTX::BI__bmma_m8n8k128_mma_xor_popc_b1) SatfArg = 0; // .b1 does not have satf argument. - else if (Optional OptSatfArg = - E->getArg(5)->getIntegerConstantExpr(getContext())) - SatfArg = *OptSatfArg; - else + else if (!E->getArg(5)->isIntegerConstantExpr(SatfArg, getContext())) return nullptr; bool Satf = SatfArg.getSExtValue(); NVPTXMmaInfo MI = getNVPTXMmaInfo(BuiltinID); @@ -16257,8 +16271,9 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, case WebAssembly::BI__builtin_wasm_extract_lane_i64x2: case WebAssembly::BI__builtin_wasm_extract_lane_f32x4: case WebAssembly::BI__builtin_wasm_extract_lane_f64x2: { - llvm::APSInt LaneConst = - *E->getArg(1)->getIntegerConstantExpr(getContext()); + llvm::APSInt LaneConst; + if (!E->getArg(1)->isIntegerConstantExpr(LaneConst, getContext())) + llvm_unreachable("Constant arg isn't actually constant?"); Value *Vec = EmitScalarExpr(E->getArg(0)); Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst); Value *Extract = Builder.CreateExtractElement(Vec, Lane); @@ -16284,8 +16299,9 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, case WebAssembly::BI__builtin_wasm_replace_lane_i64x2: case WebAssembly::BI__builtin_wasm_replace_lane_f32x4: case WebAssembly::BI__builtin_wasm_replace_lane_f64x2: { - llvm::APSInt LaneConst = - *E->getArg(1)->getIntegerConstantExpr(getContext()); + llvm::APSInt LaneConst; + if (!E->getArg(1)->isIntegerConstantExpr(LaneConst, getContext())) + llvm_unreachable("Constant arg isn't actually constant?"); Value *Vec = EmitScalarExpr(E->getArg(0)); Value *Lane = llvm::ConstantInt::get(getLLVMContext(), LaneConst); Value *Val = EmitScalarExpr(E->getArg(2)); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index ab29e32929ceb..9e8770573d701 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3868,17 +3868,15 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, llvm::APSInt ConstLength; if (Length) { // Idx = LowerBound + Length - 1; - if (Optional CL = Length->getIntegerConstantExpr(C)) { - ConstLength = CL->zextOrTrunc(PointerWidthInBits); + if (Length->isIntegerConstantExpr(ConstLength, C)) { + ConstLength = ConstLength.zextOrTrunc(PointerWidthInBits); Length = nullptr; } auto *LowerBound = E->getLowerBound(); llvm::APSInt ConstLowerBound(PointerWidthInBits, /*isUnsigned=*/false); - if (LowerBound) { - if (Optional LB = LowerBound->getIntegerConstantExpr(C)) { - ConstLowerBound = LB->zextOrTrunc(PointerWidthInBits); - LowerBound = nullptr; - } + if (LowerBound && LowerBound->isIntegerConstantExpr(ConstLowerBound, C)) { + ConstLowerBound = ConstLowerBound.zextOrTrunc(PointerWidthInBits); + LowerBound = nullptr; } if (!Length) --ConstLength; @@ -3915,10 +3913,8 @@ LValue CodeGenFunction::EmitOMPArraySectionExpr(const OMPArraySectionExpr *E, : BaseTy; if (auto *VAT = C.getAsVariableArrayType(ArrayTy)) { Length = VAT->getSizeExpr(); - if (Optional L = Length->getIntegerConstantExpr(C)) { - ConstLength = *L; + if (Length->isIntegerConstantExpr(ConstLength, C)) Length = nullptr; - } } else { auto *CAT = C.getAsConstantArrayType(ArrayTy); ConstLength = CAT->getSize(); diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index f9785e4bea5e2..b354e810974c4 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -300,18 +300,20 @@ void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, // If specified then alignment must be a "small" power of two. unsigned AlignmentVal = 0; if (Alignment) { - Optional Val; + llvm::APSInt Val; // pack(0) is like pack(), which just works out since that is what // we use 0 for in PackAttr. - if (Alignment->isTypeDependent() || Alignment->isValueDependent() || - !(Val = Alignment->getIntegerConstantExpr(Context)) || - !(*Val == 0 || Val->isPowerOf2()) || Val->getZExtValue() > 16) { + if (Alignment->isTypeDependent() || + Alignment->isValueDependent() || + !Alignment->isIntegerConstantExpr(Val, Context) || + !(Val == 0 || Val.isPowerOf2()) || + Val.getZExtValue() > 16) { Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); return; // Ignore } - AlignmentVal = (unsigned)Val->getZExtValue(); + AlignmentVal = (unsigned) Val.getZExtValue(); } if (Action == Sema::PSK_Show) { // Show the current alignment, making sure to show the right value diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index c501c706a97bc..efaf36a693061 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -2284,7 +2284,10 @@ bool Sema::CheckARMCoprocessorImmediate(const TargetInfo &TI, if (CoprocArg->isTypeDependent() || CoprocArg->isValueDependent()) return false; - llvm::APSInt CoprocNoAP = *CoprocArg->getIntegerConstantExpr(Context); + llvm::APSInt CoprocNoAP; + bool IsICE = CoprocArg->isIntegerConstantExpr(CoprocNoAP, Context); + (void)IsICE; + assert(IsICE && "Coprocossor immediate is not a constant expression"); int64_t CoprocNo = CoprocNoAP.getExtValue(); assert(CoprocNo >= 0 && "Coprocessor immediate must be non-negative"); @@ -2596,7 +2599,8 @@ bool Sema::CheckBPFBuiltinFunctionCall(unsigned BuiltinID, // The second argument needs to be a constant int Arg = TheCall->getArg(1); - if (!Arg->isIntegerConstantExpr(Context)) { + llvm::APSInt Value; + if (!Arg->isIntegerConstantExpr(Value, Context)) { Diag(Arg->getBeginLoc(), diag::err_preserve_field_info_not_const) << 2 << Arg->getSourceRange(); return true; @@ -3194,10 +3198,11 @@ bool Sema::CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { if (BuiltinID == SystemZ::BI__builtin_tabort) { Expr *Arg = TheCall->getArg(0); - if (Optional AbortCode = Arg->getIntegerConstantExpr(Context)) - if (AbortCode->getSExtValue() >= 0 && AbortCode->getSExtValue() < 256) - return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code) - << Arg->getSourceRange(); + llvm::APSInt AbortCode(32); + if (Arg->isIntegerConstantExpr(AbortCode, Context) && + AbortCode.getSExtValue() >= 0 && AbortCode.getSExtValue() < 256) + return Diag(Arg->getBeginLoc(), diag::err_systemz_invalid_tabort_code) + << Arg->getSourceRange(); } // For intrinsics which take an immediate value as part of the instruction, @@ -4918,21 +4923,21 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, } if (SubExprs.size() >= 2 && Form != Init) { - if (Optional Result = - SubExprs[1]->getIntegerConstantExpr(Context)) - if (!isValidOrderingForOp(Result->getSExtValue(), Op)) - Diag(SubExprs[1]->getBeginLoc(), - diag::warn_atomic_op_has_invalid_memory_order) - << SubExprs[1]->getSourceRange(); + llvm::APSInt Result(32); + if (SubExprs[1]->isIntegerConstantExpr(Result, Context) && + !isValidOrderingForOp(Result.getSExtValue(), Op)) + Diag(SubExprs[1]->getBeginLoc(), + diag::warn_atomic_op_has_invalid_memory_order) + << SubExprs[1]->getSourceRange(); } if (auto ScopeModel = AtomicExpr::getScopeModel(Op)) { auto *Scope = Args[Args.size() - 1]; - if (Optional Result = - Scope->getIntegerConstantExpr(Context)) { - if (!ScopeModel->isValid(Result->getZExtValue())) - Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope) - << Scope->getSourceRange(); + llvm::APSInt Result(32); + if (Scope->isIntegerConstantExpr(Result, Context) && + !ScopeModel->isValid(Result.getZExtValue())) { + Diag(Scope->getBeginLoc(), diag::err_atomic_op_has_invalid_synch_scope) + << Scope->getSourceRange(); } SubExprs.push_back(Scope); } @@ -5800,7 +5805,8 @@ bool Sema::SemaBuiltinVSX(CallExpr *TheCall) { << TheCall->getSourceRange(); // Check the third argument is a compile time constant - if (!TheCall->getArg(2)->isIntegerConstantExpr(Context)) + llvm::APSInt Value; + if(!TheCall->getArg(2)->isIntegerConstantExpr(Value, Context)) return Diag(TheCall->getBeginLoc(), diag::err_vsx_builtin_nonconstant_argument) << 3 /* argument index */ << TheCall->getDirectCallee() @@ -5895,18 +5901,17 @@ ExprResult Sema::SemaBuiltinShuffleVector(CallExpr *TheCall) { TheCall->getArg(i)->isValueDependent()) continue; - Optional Result; - if (!(Result = TheCall->getArg(i)->getIntegerConstantExpr(Context))) + llvm::APSInt Result(32); + if (!TheCall->getArg(i)->isIntegerConstantExpr(Result, Context)) return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_nonconstant_argument) << TheCall->getArg(i)->getSourceRange()); // Allow -1 which will be translated to undef in the IR. - if (Result->isSigned() && Result->isAllOnesValue()) + if (Result.isSigned() && Result.isAllOnesValue()) continue; - if (Result->getActiveBits() > 64 || - Result->getZExtValue() >= numElements * 2) + if (Result.getActiveBits() > 64 || Result.getZExtValue() >= numElements*2) return ExprError(Diag(TheCall->getBeginLoc(), diag::err_shufflevector_argument_too_large) << TheCall->getArg(i)->getSourceRange()); @@ -6153,11 +6158,10 @@ bool Sema::SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, if (Arg->isTypeDependent() || Arg->isValueDependent()) return false; - Optional R; - if (!(R = Arg->getIntegerConstantExpr(Context))) + if (!Arg->isIntegerConstantExpr(Result, Context)) return Diag(TheCall->getBeginLoc(), diag::err_constant_integer_arg_type) << FDecl->getDeclName() << Arg->getSourceRange(); - Result = *R; + return false; } @@ -10317,15 +10321,14 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, // If the shift amount is a positive constant, drop the width by // that much. - if (Optional shift = - BO->getRHS()->getIntegerConstantExpr(C)) { - if (shift->isNonNegative()) { - unsigned zext = shift->getZExtValue(); - if (zext >= L.Width) - L.Width = (L.NonNegative ? 0 : 1); - else - L.Width -= zext; - } + llvm::APSInt shift; + if (BO->getRHS()->isIntegerConstantExpr(shift, C) && + shift.isNonNegative()) { + unsigned zext = shift.getZExtValue(); + if (zext >= L.Width) + L.Width = (L.NonNegative ? 0 : 1); + else + L.Width -= zext; } return L; @@ -10349,9 +10352,9 @@ static IntRange GetExprRange(ASTContext &C, const Expr *E, unsigned MaxWidth, IntRange L = GetExprRange(C, BO->getLHS(), opWidth, InConstantContext); // If the divisor is constant, use that. - if (Optional divisor = - BO->getRHS()->getIntegerConstantExpr(C)) { - unsigned log2 = divisor->logBase2(); // floor(log_2(divisor)) + llvm::APSInt divisor; + if (BO->getRHS()->isIntegerConstantExpr(divisor, C)) { + unsigned log2 = divisor.logBase2(); // floor(log_2(divisor)) if (log2 >= L.Width) L.Width = (L.NonNegative ? 0 : 1); else @@ -10783,20 +10786,23 @@ static void AnalyzeComparison(Sema &S, BinaryOperator *E) { Expr *RHS = E->getRHS(); if (T->isIntegralType(S.Context)) { - Optional RHSValue = RHS->getIntegerConstantExpr(S.Context); - Optional LHSValue = LHS->getIntegerConstantExpr(S.Context); + llvm::APSInt RHSValue; + llvm::APSInt LHSValue; + + bool IsRHSIntegralLiteral = RHS->isIntegerConstantExpr(RHSValue, S.Context); + bool IsLHSIntegralLiteral = LHS->isIntegerConstantExpr(LHSValue, S.Context); // We don't care about expressions whose result is a constant. - if (RHSValue && LHSValue) + if (IsRHSIntegralLiteral && IsLHSIntegralLiteral) return AnalyzeImpConvsInComparison(S, E); // We only care about expressions where just one side is literal - if ((bool)RHSValue ^ (bool)LHSValue) { + if (IsRHSIntegralLiteral ^ IsLHSIntegralLiteral) { // Is the constant on the RHS or LHS? - const bool RhsConstant = (bool)RHSValue; + const bool RhsConstant = IsRHSIntegralLiteral; Expr *Const = RhsConstant ? RHS : LHS; Expr *Other = RhsConstant ? LHS : RHS; - const llvm::APSInt &Value = RhsConstant ? *RHSValue : *LHSValue; + const llvm::APSInt &Value = RhsConstant ? RHSValue : LHSValue; // Check whether an integer constant comparison results in a value // of 'true' or 'false'. @@ -11754,8 +11760,8 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (SourcePrecision > 0 && TargetPrecision > 0 && SourcePrecision > TargetPrecision) { - if (Optional SourceInt = - E->getIntegerConstantExpr(S.Context)) { + llvm::APSInt SourceInt; + if (E->isIntegerConstantExpr(SourceInt, S.Context)) { // If the source integer is a constant, convert it to the target // floating point type. Issue a warning if the value changes // during the whole conversion. @@ -11763,11 +11769,11 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, S.Context.getFloatTypeSemantics(QualType(TargetBT, 0))); llvm::APFloat::opStatus ConversionStatus = TargetFloatValue.convertFromAPInt( - *SourceInt, SourceBT->isSignedInteger(), + SourceInt, SourceBT->isSignedInteger(), llvm::APFloat::rmNearestTiesToEven); if (ConversionStatus != llvm::APFloat::opOK) { - std::string PrettySourceValue = SourceInt->toString(10); + std::string PrettySourceValue = SourceInt.toString(10); SmallString<32> PrettyTargetValue; TargetFloatValue.toString(PrettyTargetValue, TargetPrecision); @@ -14118,10 +14124,9 @@ namespace { return; if (Expr *RHS = BinOp->getRHS()) { RHS = RHS->IgnoreParenCasts(); - Optional Value; + llvm::APSInt Value; VarWillBeReased = - (RHS && (Value = RHS->getIntegerConstantExpr(Context)) && - *Value == 0); + (RHS && RHS->isIntegerConstantExpr(Value, Context) && Value == 0); } } } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index dc0f3d68fde38..f5e375134c293 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13141,20 +13141,20 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { if (!MagicValueExpr) { continue; } - Optional MagicValueInt; - if (!(MagicValueInt = MagicValueExpr->getIntegerConstantExpr(Context))) { + llvm::APSInt MagicValueInt; + if (!MagicValueExpr->isIntegerConstantExpr(MagicValueInt, Context)) { Diag(I->getRange().getBegin(), diag::err_type_tag_for_datatype_not_ice) << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); continue; } - if (MagicValueInt->getActiveBits() > 64) { + if (MagicValueInt.getActiveBits() > 64) { Diag(I->getRange().getBegin(), diag::err_type_tag_for_datatype_too_large) << LangOpts.CPlusPlus << MagicValueExpr->getSourceRange(); continue; } - uint64_t MagicValue = MagicValueInt->getZExtValue(); + uint64_t MagicValue = MagicValueInt.getZExtValue(); RegisterTypeTagForDatatype(I->getArgumentKind(), MagicValue, I->getMatchingCType(), diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index ece93cbd6a9bd..1a0594512a606 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -240,9 +240,9 @@ template static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, uint32_t &Val, unsigned Idx = UINT_MAX, bool StrictlyUnsigned = false) { - Optional I = llvm::APSInt(32); + llvm::APSInt I(32); if (Expr->isTypeDependent() || Expr->isValueDependent() || - !(I = Expr->getIntegerConstantExpr(S.Context))) { + !Expr->isIntegerConstantExpr(I, S.Context)) { if (Idx != UINT_MAX) S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) << &AI << Idx << AANT_ArgumentIntegerConstant @@ -253,19 +253,19 @@ static bool checkUInt32Argument(Sema &S, const AttrInfo &AI, const Expr *Expr, return false; } - if (!I->isIntN(32)) { + if (!I.isIntN(32)) { S.Diag(Expr->getExprLoc(), diag::err_ice_too_large) - << I->toString(10, false) << 32 << /* Unsigned */ 1; + << I.toString(10, false) << 32 << /* Unsigned */ 1; return false; } - if (StrictlyUnsigned && I->isSigned() && I->isNegative()) { + if (StrictlyUnsigned && I.isSigned() && I.isNegative()) { S.Diag(getAttrLoc(AI), diag::err_attribute_requires_positive_integer) << &AI << /*non-negative*/ 1; return false; } - Val = (uint32_t)I->getZExtValue(); + Val = (uint32_t)I.getZExtValue(); return true; } @@ -332,16 +332,16 @@ static bool checkFunctionOrMethodParameterIndex( unsigned NumParams = (HP ? getFunctionOrMethodNumParams(D) : 0) + HasImplicitThisParam; - Optional IdxInt; + llvm::APSInt IdxInt; if (IdxExpr->isTypeDependent() || IdxExpr->isValueDependent() || - !(IdxInt = IdxExpr->getIntegerConstantExpr(S.Context))) { + !IdxExpr->isIntegerConstantExpr(IdxInt, S.Context)) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_n_type) << &AI << AttrArgNum << AANT_ArgumentIntegerConstant << IdxExpr->getSourceRange(); return false; } - unsigned IdxSource = IdxInt->getLimitedValue(UINT_MAX); + unsigned IdxSource = IdxInt.getLimitedValue(UINT_MAX); if (IdxSource < 1 || (!IV && IdxSource > NumParams)) { S.Diag(getAttrLoc(AI), diag::err_attribute_argument_out_of_bounds) << &AI << AttrArgNum << IdxExpr->getSourceRange(); @@ -1605,8 +1605,8 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, } if (!E->isValueDependent()) { - Optional I = llvm::APSInt(64); - if (!(I = E->getIntegerConstantExpr(Context))) { + llvm::APSInt I(64); + if (!E->isIntegerConstantExpr(I, Context)) { if (OE) Diag(AttrLoc, diag::err_attribute_argument_n_type) << &TmpAttr << 1 << AANT_ArgumentIntegerConstant @@ -1618,22 +1618,27 @@ void Sema::AddAssumeAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, return; } - if (!I->isPowerOf2()) { + if (!I.isPowerOf2()) { Diag(AttrLoc, diag::err_alignment_not_power_of_two) << E->getSourceRange(); return; } - if (*I > Sema::MaximumAlignment) + if (I > Sema::MaximumAlignment) Diag(CI.getLoc(), diag::warn_assume_aligned_too_great) << CI.getRange() << Sema::MaximumAlignment; } - if (OE && !OE->isValueDependent() && !OE->isIntegerConstantExpr(Context)) { - Diag(AttrLoc, diag::err_attribute_argument_n_type) - << &TmpAttr << 2 << AANT_ArgumentIntegerConstant - << OE->getSourceRange(); - return; + if (OE) { + if (!OE->isValueDependent()) { + llvm::APSInt I(64); + if (!OE->isIntegerConstantExpr(I, Context)) { + Diag(AttrLoc, diag::err_attribute_argument_n_type) + << &TmpAttr << 2 << AANT_ArgumentIntegerConstant + << OE->getSourceRange(); + return; + } + } } D->addAttr(::new (Context) AssumeAlignedAttr(Context, CI, E, OE)); @@ -2724,36 +2729,36 @@ static void handleSentinelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { unsigned sentinel = (unsigned)SentinelAttr::DefaultSentinel; if (AL.getNumArgs() > 0) { Expr *E = AL.getArgAsExpr(0); - Optional Idx = llvm::APSInt(32); + llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || - !(Idx = E->getIntegerConstantExpr(S.Context))) { + !E->isIntegerConstantExpr(Idx, S.Context)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL << 1 << AANT_ArgumentIntegerConstant << E->getSourceRange(); return; } - if (Idx->isSigned() && Idx->isNegative()) { + if (Idx.isSigned() && Idx.isNegative()) { S.Diag(AL.getLoc(), diag::err_attribute_sentinel_less_than_zero) << E->getSourceRange(); return; } - sentinel = Idx->getZExtValue(); + sentinel = Idx.getZExtValue(); } unsigned nullPos = (unsigned)SentinelAttr::DefaultNullPos; if (AL.getNumArgs() > 1) { Expr *E = AL.getArgAsExpr(1); - Optional Idx = llvm::APSInt(32); + llvm::APSInt Idx(32); if (E->isTypeDependent() || E->isValueDependent() || - !(Idx = E->getIntegerConstantExpr(S.Context))) { + !E->isIntegerConstantExpr(Idx, S.Context)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) << AL << 2 << AANT_ArgumentIntegerConstant << E->getSourceRange(); return; } - nullPos = Idx->getZExtValue(); + nullPos = Idx.getZExtValue(); - if ((Idx->isSigned() && Idx->isNegative()) || nullPos > 1) { + if ((Idx.isSigned() && Idx.isNegative()) || nullPos > 1) { // FIXME: This error message could be improved, it would be nice // to say what the bounds actually are. S.Diag(AL.getLoc(), diag::err_attribute_sentinel_not_zero_or_one) @@ -4828,19 +4833,19 @@ static Expr *makeLaunchBoundsArgExpr(Sema &S, Expr *E, if (E->isValueDependent()) return E; - Optional I = llvm::APSInt(64); - if (!(I = E->getIntegerConstantExpr(S.Context))) { + llvm::APSInt I(64); + if (!E->isIntegerConstantExpr(I, S.Context)) { S.Diag(E->getExprLoc(), diag::err_attribute_argument_n_type) << &AL << Idx << AANT_ArgumentIntegerConstant << E->getSourceRange(); return nullptr; } // Make sure we can fit it in 32 bits. - if (!I->isIntN(32)) { - S.Diag(E->getExprLoc(), diag::err_ice_too_large) - << I->toString(10, false) << 32 << /* Unsigned */ 1; + if (!I.isIntN(32)) { + S.Diag(E->getExprLoc(), diag::err_ice_too_large) << I.toString(10, false) + << 32 << /* Unsigned */ 1; return nullptr; } - if (*I < 0) + if (I < 0) S.Diag(E->getExprLoc(), diag::warn_attribute_argument_n_negative) << &AL << Idx << E->getSourceRange(); @@ -5681,18 +5686,18 @@ static void handleMSP430InterruptAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } Expr *NumParamsExpr = static_cast(AL.getArgAsExpr(0)); - Optional NumParams = llvm::APSInt(32); - if (!(NumParams = NumParamsExpr->getIntegerConstantExpr(S.Context))) { + llvm::APSInt NumParams(32); + if (!NumParamsExpr->isIntegerConstantExpr(NumParams, S.Context)) { S.Diag(AL.getLoc(), diag::err_attribute_argument_type) << AL << AANT_ArgumentIntegerConstant << NumParamsExpr->getSourceRange(); return; } // The argument should be in range 0..63. - unsigned Num = NumParams->getLimitedValue(255); + unsigned Num = NumParams.getLimitedValue(255); if (Num > 63) { S.Diag(AL.getLoc(), diag::err_attribute_argument_out_of_bounds) - << AL << (int)NumParams->getSExtValue() + << AL << (int)NumParams.getSExtValue() << NumParamsExpr->getSourceRange(); return; } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index e3aa817c62249..d885920b6c14e 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2073,29 +2073,29 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // per CWG1464. Otherwise, if it's not a constant, we must have an // unparenthesized array type. if (!(*ArraySize)->isValueDependent()) { + llvm::APSInt Value; // We've already performed any required implicit conversion to integer or // unscoped enumeration type. // FIXME: Per CWG1464, we are required to check the value prior to // converting to size_t. This will never find a negative array size in // C++14 onwards, because Value is always unsigned here! - if (Optional Value = - (*ArraySize)->getIntegerConstantExpr(Context)) { - if (Value->isSigned() && Value->isNegative()) { + if ((*ArraySize)->isIntegerConstantExpr(Value, Context)) { + if (Value.isSigned() && Value.isNegative()) { return ExprError(Diag((*ArraySize)->getBeginLoc(), diag::err_typecheck_negative_array_size) << (*ArraySize)->getSourceRange()); } if (!AllocType->isDependentType()) { - unsigned ActiveSizeBits = ConstantArrayType::getNumAddressingBits( - Context, AllocType, *Value); + unsigned ActiveSizeBits = + ConstantArrayType::getNumAddressingBits(Context, AllocType, Value); if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) return ExprError( Diag((*ArraySize)->getBeginLoc(), diag::err_array_too_large) - << Value->toString(10) << (*ArraySize)->getSourceRange()); + << Value.toString(10) << (*ArraySize)->getSourceRange()); } - KnownArraySize = Value->getZExtValue(); + KnownArraySize = Value.getZExtValue(); } else if (TypeIdParens.isValid()) { // Can't have dynamic array size when the type-id is in parentheses. Diag((*ArraySize)->getBeginLoc(), diag::ext_new_paren_array_nonconst) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index d1ddf10724172..b27abb54c170f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5989,7 +5989,8 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG, // Deal with non-constant score and user condition expressions. auto HandleNonConstantScoresAndConditions = [this](Expr *&E, bool IsScore) -> bool { - if (!E || E->isIntegerConstantExpr(Context)) + llvm::APSInt Result; + if (!E || E->isIntegerConstantExpr(Result, Context)) return false; if (IsScore) { @@ -6475,14 +6476,14 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, bool Subtract) { // loop. If test-expr is of form b relational-op var and relational-op is // > or >= then incr-expr must cause var to increase on each iteration of // the loop. - Optional Result = - NewStep->getIntegerConstantExpr(SemaRef.Context); + llvm::APSInt Result; + bool IsConstant = NewStep->isIntegerConstantExpr(Result, SemaRef.Context); bool IsUnsigned = !NewStep->getType()->hasSignedIntegerRepresentation(); bool IsConstNeg = - Result && Result->isSigned() && (Subtract != Result->isNegative()); + IsConstant && Result.isSigned() && (Subtract != Result.isNegative()); bool IsConstPos = - Result && Result->isSigned() && (Subtract == Result->isNegative()); - bool IsConstZero = Result && !Result->getBoolValue(); + IsConstant && Result.isSigned() && (Subtract == Result.isNegative()); + bool IsConstZero = IsConstant && !Result.getBoolValue(); // != with increment is treated as <; != with decrement is treated as > if (!TestIsLessOp.hasValue()) @@ -7913,9 +7914,9 @@ static ExprResult widenIterationCount(unsigned Bits, Expr *E, Sema &SemaRef) { static bool fitsInto(unsigned Bits, bool Signed, const Expr *E, Sema &SemaRef) { if (E == nullptr) return false; - if (Optional Result = - E->getIntegerConstantExpr(SemaRef.Context)) - return Signed ? Result->isSignedIntN(Bits) : Result->isIntN(Bits); + llvm::APSInt Result; + if (E->isIntegerConstantExpr(Result, SemaRef.Context)) + return Signed ? Result.isSignedIntN(Bits) : Result.isIntN(Bits); return false; } @@ -8188,7 +8189,9 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // Calculate the last iteration number beforehand instead of doing this on // each iteration. Do not do this if the number of iterations may be kfold-ed. - bool IsConstant = LastIteration.get()->isIntegerConstantExpr(SemaRef.Context); + llvm::APSInt Result; + bool IsConstant = + LastIteration.get()->isIntegerConstantExpr(Result, SemaRef.Context); ExprResult CalcLastIteration; if (!IsConstant) { ExprResult SaveRef = @@ -12579,16 +12582,15 @@ isNonNegativeIntegerValue(Expr *&ValExpr, Sema &SemaRef, OpenMPClauseKind CKind, ValExpr = Value.get(); // The expression must evaluate to a non-negative integer value. - if (Optional Result = - ValExpr->getIntegerConstantExpr(SemaRef.Context)) { - if (Result->isSigned() && - !((!StrictlyPositive && Result->isNonNegative()) || - (StrictlyPositive && Result->isStrictlyPositive()))) { - SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) - << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) - << ValExpr->getSourceRange(); - return false; - } + llvm::APSInt Result; + if (ValExpr->isIntegerConstantExpr(Result, SemaRef.Context) && + Result.isSigned() && + !((!StrictlyPositive && Result.isNonNegative()) || + (StrictlyPositive && Result.isStrictlyPositive()))) { + SemaRef.Diag(Loc, diag::err_omp_negative_expression_in_clause) + << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0) + << ValExpr->getSourceRange(); + return false; } if (!BuildCapture) return true; @@ -13213,9 +13215,9 @@ OMPClause *Sema::ActOnOpenMPScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - if (Optional Result = - ValExpr->getIntegerConstantExpr(Context)) { - if (Result->isSigned() && !Result->isStrictlyPositive()) { + llvm::APSInt Result; + if (ValExpr->isIntegerConstantExpr(Result, Context)) { + if (Result.isSigned() && !Result.isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) << "schedule" << 1 << ChunkSize->getSourceRange(); return nullptr; @@ -15686,12 +15688,12 @@ OMPClause *Sema::ActOnOpenMPLinearClause( // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). - if (Optional Result = - StepExpr->getIntegerConstantExpr(Context)) { - if (!Result->isNegative() && !Result->isStrictlyPositive()) - Diag(StepLoc, diag::warn_omp_linear_step_zero) - << Vars[0] << (Vars.size() > 1); - } else if (CalcStep.isUsable()) { + llvm::APSInt Result; + bool IsConstant = StepExpr->isIntegerConstantExpr(Result, Context); + if (IsConstant && !Result.isNegative() && !Result.isStrictlyPositive()) + Diag(StepLoc, diag::warn_omp_linear_step_zero) << Vars[0] + << (Vars.size() > 1); + if (!IsConstant && CalcStep.isUsable()) { // Calculate the step beforehand instead of doing this on each iteration. // (This is not used if the number of iterations may be kfold-ed). CalcStepExpr = CalcStep.get(); @@ -18223,9 +18225,9 @@ OMPClause *Sema::ActOnOpenMPDistScheduleClause( // OpenMP [2.7.1, Restrictions] // chunk_size must be a loop invariant integer expression with a positive // value. - if (Optional Result = - ValExpr->getIntegerConstantExpr(Context)) { - if (Result->isSigned() && !Result->isStrictlyPositive()) { + llvm::APSInt Result; + if (ValExpr->isIntegerConstantExpr(Result, Context)) { + if (Result.isSigned() && !Result.isStrictlyPositive()) { Diag(ChunkSizeLoc, diag::err_omp_negative_expression_in_clause) << "dist_schedule" << ChunkSize->getSourceRange(); return nullptr; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7c6acf011d574..8635397f48067 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -346,6 +346,7 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( ToType->isRealFloatingType()) { if (IgnoreFloatToIntegralConversion) return NK_Not_Narrowing; + llvm::APSInt IntConstantValue; const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); assert(Initializer && "Unknown conversion expression"); @@ -353,20 +354,19 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( if (Initializer->isValueDependent()) return NK_Dependent_Narrowing; - if (Optional IntConstantValue = - Initializer->getIntegerConstantExpr(Ctx)) { + if (Initializer->isIntegerConstantExpr(IntConstantValue, Ctx)) { // Convert the integer to the floating type. llvm::APFloat Result(Ctx.getFloatTypeSemantics(ToType)); - Result.convertFromAPInt(*IntConstantValue, IntConstantValue->isSigned(), + Result.convertFromAPInt(IntConstantValue, IntConstantValue.isSigned(), llvm::APFloat::rmNearestTiesToEven); // And back. - llvm::APSInt ConvertedValue = *IntConstantValue; + llvm::APSInt ConvertedValue = IntConstantValue; bool ignored; Result.convertToInteger(ConvertedValue, llvm::APFloat::rmTowardZero, &ignored); // If the resulting value is different, this was a narrowing conversion. - if (*IntConstantValue != ConvertedValue) { - ConstantValue = APValue(*IntConstantValue); + if (IntConstantValue != ConvertedValue) { + ConstantValue = APValue(IntConstantValue); ConstantType = Initializer->getType(); return NK_Constant_Narrowing; } @@ -430,18 +430,17 @@ NarrowingKind StandardConversionSequence::getNarrowingKind( (FromWidth == ToWidth && FromSigned != ToSigned) || (FromSigned && !ToSigned)) { // Not all values of FromType can be represented in ToType. + llvm::APSInt InitializerValue; const Expr *Initializer = IgnoreNarrowingConversion(Ctx, Converted); // If it's value-dependent, we can't tell whether it's narrowing. if (Initializer->isValueDependent()) return NK_Dependent_Narrowing; - Optional OptInitializerValue; - if (!(OptInitializerValue = Initializer->getIntegerConstantExpr(Ctx))) { + if (!Initializer->isIntegerConstantExpr(InitializerValue, Ctx)) { // Such conversions on variables are always narrowing. return NK_Variable_Narrowing; } - llvm::APSInt &InitializerValue = *OptInitializerValue; bool Narrowing = false; if (FromWidth < ToWidth) { // Negative -> unsigned is narrowing. Otherwise, more bits is never @@ -2184,22 +2183,21 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // compatibility. if (From) { if (FieldDecl *MemberDecl = From->getSourceBitField()) { - Optional BitWidth; + llvm::APSInt BitWidth; if (FromType->isIntegralType(Context) && - (BitWidth = - MemberDecl->getBitWidth()->getIntegerConstantExpr(Context))) { - llvm::APSInt ToSize(BitWidth->getBitWidth(), BitWidth->isUnsigned()); + MemberDecl->getBitWidth()->isIntegerConstantExpr(BitWidth, Context)) { + llvm::APSInt ToSize(BitWidth.getBitWidth(), BitWidth.isUnsigned()); ToSize = Context.getTypeSize(ToType); // Are we promoting to an int from a bitfield that fits in an int? - if (*BitWidth < ToSize || - (FromType->isSignedIntegerType() && *BitWidth <= ToSize)) { + if (BitWidth < ToSize || + (FromType->isSignedIntegerType() && BitWidth <= ToSize)) { return To->getKind() == BuiltinType::Int; } // Are we promoting to an unsigned int from an unsigned bitfield // that fits into an unsigned int? - if (FromType->isUnsignedIntegerType() && *BitWidth <= ToSize) { + if (FromType->isUnsignedIntegerType() && BitWidth <= ToSize) { return To->getKind() == BuiltinType::UInt; } diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index c7b97ec4d975a..e9d3c755eb232 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -335,15 +335,15 @@ static Attr *handleOpenCLUnrollHint(Sema &S, Stmt *St, const ParsedAttr &A, if (NumArgs == 1) { Expr *E = A.getArgAsExpr(0); - Optional ArgVal; + llvm::APSInt ArgVal(32); - if (!(ArgVal = E->getIntegerConstantExpr(S.Context))) { + if (!E->isIntegerConstantExpr(ArgVal, S.Context)) { S.Diag(A.getLoc(), diag::err_attribute_argument_type) << A << AANT_ArgumentIntegerConstant << E->getSourceRange(); return nullptr; } - int Val = ArgVal->getSExtValue(); + int Val = ArgVal.getSExtValue(); if (Val <= 0) { S.Diag(A.getRange().getBegin(), diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 13426cbf2db40..b8f7f1a581590 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2476,8 +2476,8 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc, VectorType::GenericVector); - Optional VecSize = SizeExpr->getIntegerConstantExpr(Context); - if (!VecSize) { + llvm::APSInt VecSize(32); + if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) { Diag(AttrLoc, diag::err_attribute_argument_type) << "vector_size" << AANT_ArgumentIntegerConstant << SizeExpr->getSourceRange(); @@ -2489,13 +2489,13 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr, VectorType::GenericVector); // vecSize is specified in bytes - convert to bits. - if (!VecSize->isIntN(61)) { + if (!VecSize.isIntN(61)) { // Bit size will overflow uint64. Diag(AttrLoc, diag::err_attribute_size_too_large) << SizeExpr->getSourceRange() << "vector"; return QualType(); } - uint64_t VectorSizeBits = VecSize->getZExtValue() * 8; + uint64_t VectorSizeBits = VecSize.getZExtValue() * 8; unsigned TypeSize = static_cast(Context.getTypeSize(CurType)); if (VectorSizeBits == 0) { @@ -2540,8 +2540,8 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, } if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) { - Optional vecSize = ArraySize->getIntegerConstantExpr(Context); - if (!vecSize) { + llvm::APSInt vecSize(32); + if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) { Diag(AttrLoc, diag::err_attribute_argument_type) << "ext_vector_type" << AANT_ArgumentIntegerConstant << ArraySize->getSourceRange(); @@ -2555,7 +2555,7 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize, } // Unlike gcc's vector_size attribute, the size is specified as the // number of elements, not the number of bytes. - unsigned vectorSize = static_cast(vecSize->getZExtValue()); + unsigned vectorSize = static_cast(vecSize.getZExtValue()); if (vectorSize == 0) { Diag(AttrLoc, diag::err_attribute_zero_size) @@ -6254,15 +6254,13 @@ static bool BuildAddressSpaceIndex(Sema &S, LangAS &ASIdx, const Expr *AddrSpace, SourceLocation AttrLoc) { if (!AddrSpace->isValueDependent()) { - Optional OptAddrSpace = - AddrSpace->getIntegerConstantExpr(S.Context); - if (!OptAddrSpace) { + llvm::APSInt addrSpace(32); + if (!AddrSpace->isIntegerConstantExpr(addrSpace, S.Context)) { S.Diag(AttrLoc, diag::err_attribute_argument_type) << "'address_space'" << AANT_ArgumentIntegerConstant << AddrSpace->getSourceRange(); return false; } - llvm::APSInt &addrSpace = *OptAddrSpace; // Bounds checking. if (addrSpace.isSigned()) { @@ -7714,9 +7712,9 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, } // The number of elements must be an ICE. Expr *numEltsExpr = static_cast(Attr.getArgAsExpr(0)); - Optional numEltsInt; + llvm::APSInt numEltsInt(32); if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() || - !(numEltsInt = numEltsExpr->getIntegerConstantExpr(S.Context))) { + !numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) { S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr << AANT_ArgumentIntegerConstant << numEltsExpr->getSourceRange(); @@ -7732,7 +7730,7 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr, // The total size of the vector must be 64 or 128 bits. unsigned typeSize = static_cast(S.Context.getTypeSize(CurType)); - unsigned numElts = static_cast(numEltsInt->getZExtValue()); + unsigned numElts = static_cast(numEltsInt.getZExtValue()); unsigned vecSize = typeSize * numElts; if (vecSize != 64 && vecSize != 128) { S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType; From 78443666bc18a6957d279a0f58319c8a3e57771a Mon Sep 17 00:00:00 2001 From: Atmn Patel Date: Sun, 12 Jul 2020 22:19:40 -0500 Subject: [PATCH 064/771] [OpenMP] Add firstprivate as a default data-sharing attribute to clang This implements the default(firstprivate) clause as defined in OpenMP Technical Report 8 (2.22.4). Reviewed By: jdoerfert, ABataev Differential Revision: https://reviews.llvm.org/D75591 --- .../checks/openmp-use-default-none.rst | 9 + .../checkers/openmp-use-default-none.cpp | 52 +- clang/docs/LibASTMatchersReference.html | 19 +- clang/include/clang/ASTMatchers/ASTMatchers.h | 24 +- .../clang/Basic/DiagnosticParseKinds.td | 2 + clang/lib/ASTMatchers/Dynamic/Registry.cpp | 1 + clang/lib/Parse/ParseOpenMP.cpp | 12 +- clang/lib/Sema/SemaOpenMP.cpp | 76 +- ...stribute_parallel_for_default_messages.cpp | 31 +- ...ute_parallel_for_simd_default_messages.cpp | 30 +- clang/test/OpenMP/driver.c | 1 + .../test/OpenMP/parallel_default_messages.cpp | 26 +- .../OpenMP/parallel_for_default_messages.cpp | 23 +- .../parallel_for_simd_default_messages.cpp | 23 +- clang/test/OpenMP/parallel_master_codegen.cpp | 156 ++ .../parallel_master_default_messages.cpp | 24 +- .../parallel_sections_default_messages.cpp | 6 +- .../target_parallel_default_messages.cpp | 24 +- .../target_parallel_for_default_messages.cpp | 23 +- ...get_parallel_for_simd_default_messages.cpp | 23 +- .../OpenMP/target_teams_default_messages.cpp | 24 +- ...rget_teams_distribute_default_messages.cpp | 23 +- ...stribute_parallel_for_default_messages.cpp | 23 +- ...ute_parallel_for_simd_default_messages.cpp | 23 +- clang/test/OpenMP/task_default_messages.cpp | 23 +- clang/test/OpenMP/task_messages.cpp | 16 + clang/test/OpenMP/teams_default_messages.cpp | 24 +- .../teams_distribute_default_messages.cpp | 24 +- ...stribute_parallel_for_default_messages.cpp | 24 +- ...ute_parallel_for_simd_default_messages.cpp | 23 +- ...teams_distribute_simd_default_messages.cpp | 25 +- .../ASTMatchers/ASTMatchersNarrowingTest.cpp | 1749 ++++++++--------- .../ASTMatchers/ASTMatchersNodeTest.cpp | 825 ++++---- clang/unittests/ASTMatchers/ASTMatchersTest.h | 77 +- .../include/llvm/Frontend/OpenMP/OMPKinds.def | 1 + 35 files changed, 2030 insertions(+), 1459 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/openmp-use-default-none.rst b/clang-tools-extra/docs/clang-tidy/checks/openmp-use-default-none.rst index 4223a10bd6e9b..77114100ba1cb 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/openmp-use-default-none.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/openmp-use-default-none.rst @@ -51,3 +51,12 @@ Example // WARNING: OpenMP directive ``parallel`` specifies ``default(shared)`` // clause. Consider using ``default(none)`` clause instead. } + + // ``parallel`` directive can have ``default`` clause, and said clause is + // specified, but with ``firstprivate`` kind, which is not ``none``, diagnose. + void p0_3() { + #pragma omp parallel default(firstprivate) + ; + // WARNING: OpenMP directive ``parallel`` specifies ``default(firstprivate)`` + // clause. Consider using ``default(none)`` clause instead. + } diff --git a/clang-tools-extra/test/clang-tidy/checkers/openmp-use-default-none.cpp b/clang-tools-extra/test/clang-tidy/checkers/openmp-use-default-none.cpp index 35d2d17b1e0e8..d1d3b0e441f3f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/openmp-use-default-none.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/openmp-use-default-none.cpp @@ -1,5 +1,5 @@ -// RUN: %check_clang_tidy %s openmp-use-default-none %t -- -- -fopenmp=libomp -fopenmp-version=40 -// RUN: %check_clang_tidy -std=c11 %s openmp-use-default-none %t -- -- -x c -fopenmp=libomp -fopenmp-version=40 +// RUN: %check_clang_tidy %s openmp-use-default-none %t -- -- -fopenmp=libomp -fopenmp-version=51 +// RUN: %check_clang_tidy -std=c11 %s openmp-use-default-none %t -- -- -x c -fopenmp=libomp -fopenmp-version=51 //----------------------------------------------------------------------------// // Null cases. @@ -42,6 +42,15 @@ void p0_2() { // CHECK-NOTES: :[[@LINE-3]]:22: note: existing 'default' clause specified here } +// 'parallel' directive can have 'default' clause, and said clause specified, +// but with 'firstprivate' kind, which is not 'none', diagnose. +void p0_3() { +#pragma omp parallel default(firstprivate) + ; + // CHECK-NOTES: :[[@LINE-2]]:1: warning: OpenMP directive 'parallel' specifies 'default(firstprivate)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-3]]:22: note: existing 'default' clause specified here +} + // 'task' directive. // 'task' directive can have 'default' clause, but said clause is not @@ -68,6 +77,15 @@ void p1_2() { // CHECK-NOTES: :[[@LINE-3]]:18: note: existing 'default' clause specified here } +// 'task' directive can have 'default' clause, and said clause specified, +// but with 'firstprivate' kind, which is not 'none', diagnose. +void p1_3() { +#pragma omp task default(firstprivate) + ; + // CHECK-NOTES: :[[@LINE-2]]:1: warning: OpenMP directive 'task' specifies 'default(firstprivate)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-3]]:18: note: existing 'default' clause specified here +} + // 'teams' directive. (has to be inside of 'target' directive) // 'teams' directive can have 'default' clause, but said clause is not @@ -97,6 +115,16 @@ void p2_2() { // CHECK-NOTES: :[[@LINE-3]]:19: note: existing 'default' clause specified here } +// 'teams' directive can have 'default' clause, and said clause specified, +// but with 'firstprivate' kind, which is not 'none', diagnose. +void p2_3() { +#pragma omp target +#pragma omp teams default(firstprivate) + ; + // CHECK-NOTES: :[[@LINE-2]]:1: warning: OpenMP directive 'teams' specifies 'default(firstprivate)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-3]]:19: note: existing 'default' clause specified here +} + // 'taskloop' directive. // 'taskloop' directive can have 'default' clause, but said clause is not @@ -126,6 +154,16 @@ void p3_2(const int a) { // CHECK-NOTES: :[[@LINE-4]]:22: note: existing 'default' clause specified here } +// 'taskloop' directive can have 'default' clause, and said clause specified, +// but with 'firstprivate' kind, which is not 'none', diagnose. +void p3_3(const int a) { +#pragma omp taskloop default(firstprivate) + for (int b = 0; b < a; b++) + ; + // CHECK-NOTES: :[[@LINE-3]]:1: warning: OpenMP directive 'taskloop' specifies 'default(firstprivate)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-4]]:22: note: existing 'default' clause specified here +} + //----------------------------------------------------------------------------// // Combined directives. // Let's not test every single possible permutation/combination of directives, @@ -158,3 +196,13 @@ void p4_2(const int a) { // CHECK-NOTES: :[[@LINE-3]]:1: warning: OpenMP directive 'parallel for' specifies 'default(shared)' clause, consider using 'default(none)' clause instead // CHECK-NOTES: :[[@LINE-4]]:26: note: existing 'default' clause specified here } + +// 'parallel' directive can have 'default' clause, and said clause specified, +// but with 'firstprivate' kind, which is not 'none', diagnose. +void p4_3(const int a) { +#pragma omp parallel for default(firstprivate) + for (int b = 0; b < a; b++) + ; + // CHECK-NOTES: :[[@LINE-3]]:1: warning: OpenMP directive 'parallel for' specifies 'default(firstprivate)' clause, consider using 'default(none)' clause instead + // CHECK-NOTES: :[[@LINE-4]]:26: note: existing 'default' clause specified here +} diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 2256cbf718698..60ff6ffe60567 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -676,9 +676,10 @@

Node Matchers

#pragma omp parallel default(none) #pragma omp parallel default(shared) + #pragma omp parallel default(firstprivate) #pragma omp parallel -``ompDefaultClause()`` matches ``default(none)`` and ``default(shared)``. +``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and ``default(firstprivate)``. @@ -3783,6 +3784,7 @@

Narrowing Matchers

#pragma omp parallel #pragma omp parallel default(none) #pragma omp parallel default(shared) + #pragma omp parallel default(firstprivate) ``ompDefaultClause(isNoneKind())`` matches only ``default(none)``. @@ -3796,11 +3798,26 @@

Narrowing Matchers

#pragma omp parallel #pragma omp parallel default(none) #pragma omp parallel default(shared) + #pragma omp parallel default(firstprivate) ``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``. +Matcher<OMPDefaultClause>isSharedKind +
Matches if the OpenMP ``default`` clause has ``firstprivate`` kind specified.
+
+Given
+
+  #pragma omp parallel
+  #pragma omp parallel default(none)
+  #pragma omp parallel default(shared)
+  #pragma omp parallel default(firstprivate)
+
+``ompDefaultClause(isFirstPrivateKind())`` matches only ``default(firstprivate)``.
+
+ + Matcher<OMPExecutableDirective>isAllowedToContainClauseKindOpenMPClauseKind CKind
Matches if the OpenMP directive is allowed to contain the specified OpenMP
 clause kind.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
index f16fb876cdd38..643419743a119 100644
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -7190,10 +7190,12 @@ AST_MATCHER_P(OMPExecutableDirective, hasAnyClause,
 /// \code
 ///   #pragma omp parallel default(none)
 ///   #pragma omp parallel default(shared)
+///   #pragma omp parallel default(firstprivate)
 ///   #pragma omp parallel
 /// \endcode
 ///
-/// ``ompDefaultClause()`` matches ``default(none)`` and ``default(shared)``.
+/// ``ompDefaultClause()`` matches ``default(none)``, ``default(shared)``, and
+/// ``default(firstprivate)``
 extern const internal::VariadicDynCastAllOfMatcher
     ompDefaultClause;
 
@@ -7205,6 +7207,7 @@ extern const internal::VariadicDynCastAllOfMatcher
 ///   #pragma omp parallel
 ///   #pragma omp parallel default(none)
 ///   #pragma omp parallel default(shared)
+///   #pragma omp parallel default(firstprivate)
 /// \endcode
 ///
 /// ``ompDefaultClause(isNoneKind())`` matches only ``default(none)``.
@@ -7220,6 +7223,7 @@ AST_MATCHER(OMPDefaultClause, isNoneKind) {
 ///   #pragma omp parallel
 ///   #pragma omp parallel default(none)
 ///   #pragma omp parallel default(shared)
+///   #pragma omp parallel default(firstprivate)
 /// \endcode
 ///
 /// ``ompDefaultClause(isSharedKind())`` matches only ``default(shared)``.
@@ -7227,6 +7231,24 @@ AST_MATCHER(OMPDefaultClause, isSharedKind) {
   return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_shared;
 }
 
+/// Matches if the OpenMP ``default`` clause has ``firstprivate`` kind
+/// specified.
+///
+/// Given
+///
+/// \code
+///   #pragma omp parallel
+///   #pragma omp parallel default(none)
+///   #pragma omp parallel default(shared)
+///   #pragma omp parallel default(firstprivate)
+/// \endcode
+///
+/// ``ompDefaultClause(isFirstPrivateKind())`` matches only
+/// ``default(firstprivate)``.
+AST_MATCHER(OMPDefaultClause, isFirstPrivateKind) {
+  return Node.getDefaultKind() == llvm::omp::OMP_DEFAULT_firstprivate;
+}
+
 /// Matches if the OpenMP directive is allowed to contain the specified OpenMP
 /// clause kind.
 ///
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index f5b32a6ba5fa9..1038a4119d4cb 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1334,6 +1334,8 @@ def warn_omp_more_one_device_type_clause
       InGroup;
 def err_omp_variant_ctx_second_match_extension : Error<
   "only a single match extension allowed per OpenMP context selector">;
+def err_omp_invalid_dsa: Error<
+  "data-sharing attribute '%0' in '%1' clause requires OpenMP version %2 or above">;
 
 // Pragma loop support.
 def err_pragma_loop_missing_argument : Error<
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
index a0a65092a92b4..ec2215804c098 100644
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -389,6 +389,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(isExpr);
   REGISTER_MATCHER(isExternC);
   REGISTER_MATCHER(isFinal);
+  REGISTER_MATCHER(isFirstPrivateKind);
   REGISTER_MATCHER(isImplicit);
   REGISTER_MATCHER(isInStdNamespace);
   REGISTER_MATCHER(isInTemplateInstantiation);
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index afcef30438434..5223755c8fdf1 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1441,7 +1441,7 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
 ///
 ///    default-clause:
-///         'default' '(' 'none' | 'shared' ')
+///         'default' '(' 'none' | 'shared'  | 'firstprivate' ')
 ///
 ///    proc_bind-clause:
 ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
@@ -2772,7 +2772,7 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
 ///
 ///    default-clause:
-///         'default' '(' 'none' | 'shared' ')'
+///         'default' '(' 'none' | 'shared' | 'firstprivate' ')'
 ///
 ///    proc_bind-clause:
 ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')'
@@ -2785,6 +2785,14 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
   llvm::Optional Val = parseOpenMPSimpleClause(*this, Kind);
   if (!Val || ParseOnly)
     return nullptr;
+  if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
+      static_cast(Val.getValue().Type) ==
+          OMP_DEFAULT_firstprivate) {
+    Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa)
+        << getOpenMPClauseName(OMPC_firstprivate)
+        << getOpenMPClauseName(OMPC_default) << "5.1";
+    return nullptr;
+  }
   return Actions.ActOnOpenMPSimpleClause(
       Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
       Val.getValue().Loc, Val.getValue().RLoc);
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index b27abb54c170f..920463da40277 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -53,9 +53,10 @@ static const Expr *checkMapClauseExpressionBase(
 namespace {
 /// Default data sharing attributes, which can be applied to directive.
 enum DefaultDataSharingAttributes {
-  DSA_unspecified = 0, /// Data sharing attribute not specified.
-  DSA_none = 1 << 0,   /// Default data sharing attribute 'none'.
-  DSA_shared = 1 << 1, /// Default data sharing attribute 'shared'.
+  DSA_unspecified = 0,       /// Data sharing attribute not specified.
+  DSA_none = 1 << 0,         /// Default data sharing attribute 'none'.
+  DSA_shared = 1 << 1,       /// Default data sharing attribute 'shared'.
+  DSA_firstprivate = 1 << 2, /// Default data sharing attribute 'firstprivate'.
 };
 
 /// Stack for tracking declarations used in OpenMP directives and
@@ -684,6 +685,11 @@ class DSAStackTy {
     getTopOfStack().DefaultAttr = DSA_shared;
     getTopOfStack().DefaultAttrLoc = Loc;
   }
+  /// Set default data sharing attribute to firstprivate.
+  void setDefaultDSAFirstPrivate(SourceLocation Loc) {
+    getTopOfStack().DefaultAttr = DSA_firstprivate;
+    getTopOfStack().DefaultAttrLoc = Loc;
+  }
   /// Set default data mapping attribute to Modifier:Kind
   void setDefaultDMAAttr(OpenMPDefaultmapClauseModifier M,
                          OpenMPDefaultmapClauseKind Kind,
@@ -1183,6 +1189,15 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
     return DVar;
   case DSA_none:
     return DVar;
+  case DSA_firstprivate:
+    if (VD->getStorageDuration() == SD_Static &&
+        VD->getDeclContext()->isFileContext()) {
+      DVar.CKind = OMPC_unknown;
+    } else {
+      DVar.CKind = OMPC_firstprivate;
+    }
+    DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
+    return DVar;
   case DSA_unspecified:
     // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
     // in a Construct, implicitly determined, p.2]
@@ -2058,7 +2073,13 @@ bool Sema::isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level,
         // If the variable is artificial and must be captured by value - try to
         // capture by value.
         !(isa(D) && !D->hasAttr() &&
-          !cast(D)->getInit()->isGLValue());
+          !cast(D)->getInit()->isGLValue()) &&
+        // If the variable is implicitly firstprivate and scalar - capture by
+        // copy
+        !(DSAStack->getDefaultDSA() == DSA_firstprivate &&
+          !DSAStack->hasExplicitDSA(
+              D, [](OpenMPClauseKind K) { return K != OMPC_unknown; }, Level) &&
+          !DSAStack->isLoopControlVariable(D, Level).first);
   }
 
   // When passing data by copy, we need to make sure it fits the uintptr size
@@ -2185,10 +2206,13 @@ VarDecl *Sema::isOpenMPCapturedDecl(ValueDecl *D, bool CheckScopeInfo,
         DSAStack->isClauseParsingMode());
     // Global shared must not be captured.
     if (VD && !VD->hasLocalStorage() && DVarPrivate.CKind == OMPC_unknown &&
-        (DSAStack->getDefaultDSA() != DSA_none || DVarTop.CKind == OMPC_shared))
+        ((DSAStack->getDefaultDSA() != DSA_none &&
+          DSAStack->getDefaultDSA() != DSA_firstprivate) ||
+         DVarTop.CKind == OMPC_shared))
       return nullptr;
     if (DVarPrivate.CKind != OMPC_unknown ||
-        (VD && DSAStack->getDefaultDSA() == DSA_none))
+        (VD && (DSAStack->getDefaultDSA() == DSA_none ||
+                DSAStack->getDefaultDSA() == DSA_firstprivate)))
       return VD ? VD : cast(DVarPrivate.PrivateCopy->getDecl());
   }
   return nullptr;
@@ -3333,10 +3357,19 @@ class DSAAttrChecker final : public StmtVisitor {
       // in the construct, and does not have a predetermined data-sharing
       // attribute, must have its data-sharing attribute explicitly determined
       // by being listed in a data-sharing attribute clause.
-      if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none &&
+      if (DVar.CKind == OMPC_unknown &&
+          (Stack->getDefaultDSA() == DSA_none ||
+           Stack->getDefaultDSA() == DSA_firstprivate) &&
           isImplicitOrExplicitTaskingRegion(DKind) &&
           VarsWithInheritedDSA.count(VD) == 0) {
-        VarsWithInheritedDSA[VD] = E;
+        bool InheritedDSA = Stack->getDefaultDSA() == DSA_none;
+        if (!InheritedDSA && Stack->getDefaultDSA() == DSA_firstprivate) {
+          DSAStackTy::DSAVarData DVar =
+              Stack->getImplicitDSA(VD, /*FromParent=*/false);
+          InheritedDSA = DVar.CKind == OMPC_unknown;
+        }
+        if (InheritedDSA)
+          VarsWithInheritedDSA[VD] = E;
         return;
       }
 
@@ -3438,7 +3471,9 @@ class DSAAttrChecker final : public StmtVisitor {
 
       // Define implicit data-sharing attributes for task.
       DVar = Stack->getImplicitDSA(VD, /*FromParent=*/false);
-      if (isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared &&
+      if (((isOpenMPTaskingDirective(DKind) && DVar.CKind != OMPC_shared) ||
+           (Stack->getDefaultDSA() == DSA_firstprivate &&
+            DVar.CKind == OMPC_firstprivate && !DVar.RefExpr)) &&
           !Stack->isLoopControlVariable(VD).first) {
         ImplicitFirstprivate.push_back(E);
         return;
@@ -5342,8 +5377,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
 
   ErrorFound = Res.isInvalid() || ErrorFound;
 
-  // Check variables in the clauses if default(none) was specified.
-  if (DSAStack->getDefaultDSA() == DSA_none) {
+  // Check variables in the clauses if default(none) or
+  // default(firstprivate) was specified.
+  if (DSAStack->getDefaultDSA() == DSA_none ||
+      DSAStack->getDefaultDSA() == DSA_firstprivate) {
     DSAAttrChecker DSAChecker(DSAStack, *this, nullptr);
     for (OMPClause *C : Clauses) {
       switch (C->getClauseKind()) {
@@ -5454,7 +5491,8 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
     if (P.getFirst()->isImplicit() || isa(P.getFirst()))
       continue;
     ErrorFound = true;
-    if (DSAStack->getDefaultDSA() == DSA_none) {
+    if (DSAStack->getDefaultDSA() == DSA_none ||
+        DSAStack->getDefaultDSA() == DSA_firstprivate) {
       Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable)
           << P.first << P.second->getSourceRange();
       Diag(DSAStack->getDefaultDSALocation(), diag::note_omp_default_dsa_none);
@@ -12932,10 +12970,20 @@ OMPClause *Sema::ActOnOpenMPDefaultClause(DefaultKind Kind,
         << getOpenMPClauseName(OMPC_default);
     return nullptr;
   }
-  if (Kind == OMP_DEFAULT_none)
+
+  switch (Kind) {
+  case OMP_DEFAULT_none:
     DSAStack->setDefaultDSANone(KindKwLoc);
-  else if (Kind == OMP_DEFAULT_shared)
+    break;
+  case OMP_DEFAULT_shared:
     DSAStack->setDefaultDSAShared(KindKwLoc);
+    break;
+  case OMP_DEFAULT_firstprivate:
+    DSAStack->setDefaultDSAFirstPrivate(KindKwLoc);
+    break;
+  default:
+    llvm_unreachable("DSA unexpected in OpenMP default clause");
+  }
 
   return new (Context)
       OMPDefaultClause(Kind, KindKwLoc, StartLoc, LParenLoc, EndLoc);
diff --git a/clang/test/OpenMP/distribute_parallel_for_default_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_default_messages.cpp
index 0629ba096d0c2..67e4615ae8c01 100644
--- a/clang/test/OpenMP/distribute_parallel_for_default_messages.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_default_messages.cpp
@@ -2,8 +2,17 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 template 
 T tmain(T argc) {
   int i;
@@ -14,12 +23,12 @@ T tmain(T argc) {
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp distribute parallel for default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp distribute parallel for default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
@@ -34,7 +43,7 @@ T tmain(T argc) {
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp distribute parallel for default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
@@ -62,12 +71,12 @@ int main(int argc, char **argv) {
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp distribute parallel for default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp distribute parallel for default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
@@ -82,7 +91,7 @@ int main(int argc, char **argv) {
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp distribute parallel for default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
@@ -98,5 +107,15 @@ int main(int argc, char **argv) {
   for (i = 0; i < argc; ++i) // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
     foo();
 
+#ifdef OMP51
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  for (i = 0; i < argc; ++i) {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
   return (tmain(argc) + tmain(argv[0][0])); // expected-note {{in instantiation of function template specialization 'tmain' requested here}} expected-note {{in instantiation of function template specialization 'tmain' requested here}}
 }
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_default_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_default_messages.cpp
index b9c5546ec5d95..9aab00f16c48f 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_default_messages.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_default_messages.cpp
@@ -2,8 +2,17 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -o - %s -Wuninitialized -DOMP51 -fopenmp-version=51
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized -DOMP51 -fopenmp-version=51
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 template 
 T tmain(T argc) {
   int i;
@@ -14,12 +23,12 @@ T tmain(T argc) {
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for simd default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp distribute parallel for simd default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for simd default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp distribute parallel for simd default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
@@ -34,7 +43,7 @@ T tmain(T argc) {
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for simd default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp distribute parallel for simd default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
@@ -62,12 +71,12 @@ int main(int argc, char **argv) {
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for simd default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp distribute parallel for simd default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for simd default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp distribute parallel for simd default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
@@ -82,7 +91,7 @@ int main(int argc, char **argv) {
     foo();
 #pragma omp target
 #pragma omp teams
-#pragma omp distribute parallel for simd default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp distribute parallel for simd default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target
@@ -90,6 +99,15 @@ int main(int argc, char **argv) {
 #pragma omp distribute parallel for simd default(none) // expected-note {{explicit data sharing attribute requested here}}
   for (i = 0; i < argc; ++i)  // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
     foo();
+#ifdef OpenMP51
+#pragma omp target
+#pragma omp teams
+#pragma omp distribute parallel for simd default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  for (i = 0; i < argc; ++i) {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
 
 #pragma omp parallel default(none) // expected-note 2 {{explicit data sharing attribute requested here}}
 #pragma omp target
diff --git a/clang/test/OpenMP/driver.c b/clang/test/OpenMP/driver.c
index fa5bd1a8b5f8d..047478256f9f5 100644
--- a/clang/test/OpenMP/driver.c
+++ b/clang/test/OpenMP/driver.c
@@ -47,6 +47,7 @@
 // RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=31 | FileCheck --check-prefix=CHECK-VERSION %s
 // RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=40 | FileCheck --check-prefix=CHECK-VERSION %s
 // RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=45 | FileCheck --check-prefix=CHECK-VERSION %s
+// RUN: %clang %s -c -E -dM -fopenmp-simd -fopenmp-version=51 | FileCheck --check-prefix=CHECK-VERSION %s
 
 // CHECK-VERSION-NOT: #define _OPENMP
 
diff --git a/clang/test/OpenMP/parallel_default_messages.cpp b/clang/test/OpenMP/parallel_default_messages.cpp
index 6b8ad67051850..b098c43852a85 100644
--- a/clang/test/OpenMP/parallel_default_messages.cpp
+++ b/clang/test/OpenMP/parallel_default_messages.cpp
@@ -4,18 +4,25 @@
 // RUN: %clang_cc1 -verify=expected,ge40 -fopenmp-version=40 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized
 // RUN: %clang_cc1 -verify -fopenmp-version=31 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized
 // RUN: %clang_cc1 -verify -fopenmp-version=30 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,ge40 -fopenmp-version=51 -fopenmp -DOMP51 -ferror-limit 100 -o - %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,ge40 -fopenmp-version=51 -fopenmp-simd -DOMP51 -ferror-limit 100 -o - %s -Wuninitialized
 
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   const int c = 0;
 
   #pragma omp parallel default // expected-error {{expected '(' after 'default'}}
-  #pragma omp parallel default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-  #pragma omp parallel default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
-  #pragma omp parallel default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
-  #pragma omp parallel default (shared), default(shared) // expected-error {{directive '#pragma omp parallel' cannot contain more than one 'default' clause}}
-  #pragma omp parallel default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel default(  // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp parallel default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
+#pragma omp parallel default(none                     // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp parallel default(shared), default(shared) // expected-error {{directive '#pragma omp parallel' cannot contain more than one 'default' clause}}
+#pragma omp parallel default(x)                       // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   foo();
 
   #pragma omp parallel default(none) // expected-note {{explicit data sharing attribute requested here}}
@@ -27,5 +34,14 @@ int main(int argc, char **argv) {
 
   #pragma omp parallel default(none) // ge40-note {{explicit data sharing attribute requested here}}
   (void)c; // ge40-error {{variable 'c' must have explicitly specified data sharing attributes}}
+
+#ifdef OMP51
+#pragma omp parallel default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/parallel_for_default_messages.cpp b/clang/test/OpenMP/parallel_for_default_messages.cpp
index b02fa8803a3b3..c64b76948c018 100644
--- a/clang/test/OpenMP/parallel_for_default_messages.cpp
+++ b/clang/test/OpenMP/parallel_for_default_messages.cpp
@@ -2,17 +2,26 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -DOMP51 -ferror-limit 100 -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -DOMP51 -ferror-limit 100 -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   int i;
 #pragma omp parallel for default // expected-error {{expected '(' after 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp parallel for default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp parallel for default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp parallel for default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel for default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp parallel for default(none // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{explicit data sharing attribute requested here}}
@@ -21,7 +30,7 @@ int main(int argc, char **argv) {
 #pragma omp parallel for default(shared), default(shared) // expected-error {{directive '#pragma omp parallel for' cannot contain more than one 'default' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp parallel for default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel for default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 
@@ -34,5 +43,13 @@ int main(int argc, char **argv) {
   for (i = 0; i < argc; ++i) // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
     foo();
 
+#ifdef OMP51
+#pragma omp parallel for default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  for (i = 0; i < argc; ++i) {
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/parallel_for_simd_default_messages.cpp b/clang/test/OpenMP/parallel_for_simd_default_messages.cpp
index 570ee14bbc84b..6368d280de5db 100644
--- a/clang/test/OpenMP/parallel_for_simd_default_messages.cpp
+++ b/clang/test/OpenMP/parallel_for_simd_default_messages.cpp
@@ -2,17 +2,26 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   int i;
 #pragma omp parallel for simd default // expected-error {{expected '(' after 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp parallel for simd default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp parallel for simd default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp parallel for simd default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel for simd default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp parallel for simd default(none // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{explicit data sharing attribute requested here}}
@@ -21,7 +30,7 @@ int main(int argc, char **argv) {
 #pragma omp parallel for simd default(shared), default(shared) // expected-error {{directive '#pragma omp parallel for simd' cannot contain more than one 'default' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp parallel for simd default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel for simd default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 
@@ -34,5 +43,13 @@ int main(int argc, char **argv) {
   for (i = 0; i < argc; ++i) // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}} expected-error {{variable 'i' must have explicitly specified data sharing attributes}}
     foo();
 
+#ifdef OMP51
+#pragma omp parallel for default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  for (i = 0; i < argc; ++i) {
+    x++; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    y++; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/parallel_master_codegen.cpp b/clang/test/OpenMP/parallel_master_codegen.cpp
index 9ffa941314b98..82e18c80f103e 100644
--- a/clang/test/OpenMP/parallel_master_codegen.cpp
+++ b/clang/test/OpenMP/parallel_master_codegen.cpp
@@ -118,6 +118,162 @@ void parallel_master_private() {
 
 #endif
 
+#ifdef CK31
+///==========================================================================///
+// RUN: %clang_cc1 -DCK31 -fopenmp-version=51 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s --check-prefix CK31
+// RUN: %clang_cc1 -DCK31 -fopenmp-version=51 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK31 -fopenmp-version=51 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK31
+
+// RUN: %clang_cc1 -DCK31 -fopenmp-version=51 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK31 -fopenmp-version=51 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK31 -fopenmp-version=51 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// CK31-DAG:   %struct.ident_t = type { i32, i32, i32, i32, i8* }
+// CK31-DAG:   [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
+
+void parallel_master_default_firstprivate() {
+  int a;
+#pragma omp parallel master default(firstprivate)
+  a++;
+}
+
+// CK31-LABEL: define void @{{.+}}parallel_master{{.+}}
+// CK31:       [[A_VAL:%.+]] = alloca i32{{.+}}
+// CK31:       [[A_CASTED:%.+]] = alloca i64
+// CK31:       [[ZERO_VAL:%.+]] = load i32, i32* [[A_VAL]]
+// CK31:       [[CONV:%.+]] = bitcast i64* [[A_CASTED]] to i32*
+// CK31:       store i32 [[ZERO_VAL]], i32* [[CONV]]
+// CK31:       [[ONE_VAL:%.+]] = load i64, i64* [[A_CASTED]]
+// CK31:       call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i64 [[ONE_VAL]])
+// CK31:       ret void
+
+// CK31:       [[GLOBAL_TID_ADDR:%.+]] = alloca i32*
+// CK31:       [[BOUND_TID_ADDR:%.+]] = alloca i32*
+// CK31:       [[A_ADDR:%.+]] = alloca i64{{.+}}
+// CK31:       store i32* [[GLOBAL_TID:%.+]], i32** [[GLOBAL_TID_ADDR]]{{.+}}
+// CK31:       store i32* [[BOUND_TID:%.+]], i32** [[BOUND_TID_ADDR]]
+// CK31:       store i64 [[A_VAL]], i64* [[A_ADDR]]
+// CK31:       [[CONV]] = bitcast i64* [[A_ADDR]]
+// CK31:       [[ZERO_VAL]] = load i32*, i32** [[GLOBAL_TID_ADDR]]
+// CK31:       [[ONE_VAL]] = load i32, i32* [[ZERO_VAL]]
+// CK31:       [[TWO_VAL:%.+]] = call i32 @__kmpc_master(%struct.ident_t* @0, i32 [[ONE_VAL]])
+// CK31:       [[THREE:%.+]] = icmp ne i32 [[TWO_VAL]], 0
+// CK31:       br i1 %3, label [[OMP_IF_THEN:%.+]], label [[OMP_IF_END:%.+]]
+
+// CK31:       [[FOUR:%.+]] = load i32, i32* [[CONV:%.+]]
+// CK31:       [[INC:%.+]] = add nsw i32 [[FOUR]]
+// CK31:       store i32 [[INC]], i32* [[CONV]]
+// CK31:       call void @__kmpc_end_master(%struct.ident_t* @0, i32 [[ONE_VAL]])
+// CK31:       br label [[OMP_IF_END]]
+
+// CK31:       ret void
+
+#endif
+
+#ifdef CK32
+///==========================================================================///
+// RUN: %clang_cc1 -DCK32 -fopenmp-version=51 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s --check-prefix CK32
+// RUN: %clang_cc1 -DCK32 -fopenmp-version=51 -fopenmp -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK32 -fopenmp-version=51 -fopenmp -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s --check-prefix CK32
+
+// RUN: %clang_cc1 -DCK32 -fopenmp-version=51 -verify -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// RUN: %clang_cc1 -DCK32 -fopenmp-version=51 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -emit-pch -o %t %s
+// RUN: %clang_cc1 -DCK32 -fopenmp-version=51 -fopenmp-simd -x c++ -triple x86_64-unknown-unknown -fexceptions -fcxx-exceptions -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
+// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
+
+// CK32-DAG:   %struct.ident_t = type { i32, i32, i32, i32, i8* }
+// CK32-DAG:   [[STR:@.+]] = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00"
+
+struct St {
+  int a, b;
+  static int y;
+  St() : a(0), b(0) {}
+  ~St() {}
+};
+int St::y = 0;
+
+void parallel_master_default_firstprivate() {
+  St a = St();
+  static int y = 0;
+#pragma omp parallel master default(firstprivate)
+  {
+    a.a += 1;
+    a.b += 1;
+    y++;
+    a.y++;
+  }
+}
+
+// CK32-LABEL: define {{.+}} @{{.+}}parallel_master_default_firstprivate{{.+}}
+// CK32: [[A_VAL:%.+]] = alloca %struct.St{{.+}}
+// CK32: [[Y_CASTED:%.+]] = alloca i64
+// CK32: call void @[[CTOR:.+]](%struct.St* [[A_VAL]])
+// CK32: [[ZERO:%.+]] = load i32, i32* @{{.+}}parallel_master_default_firstprivate{{.+}}
+// CK32: [[CONV:%.+]] = bitcast i64* [[Y_CASTED]] to i32*
+// CK32: store i32 [[ZERO]], i32* [[CONV]]
+// CK32: [[ONE:%.+]] = load i64, i64* [[Y_CASTED]]
+// CK32: call void {{.+}}@{{.+}} %struct.St* [[A_VAL]], i64 [[ONE]])
+// CK32: call void [[DTOR:@.+]](%struct.St* [[A_VAL]])
+
+// CK32: [[THIS_ADDR:%.+]] = alloca %struct.St*
+// CK32: store %struct.St* [[THIS:%.+]], %struct.St** [[THIS_ADDR]]
+// CK32: [[THIS_ONE:%.+]] = load %struct.St*, %struct.St** [[THIS_ADDR]]
+// CK32: call void [[CTOR_2:.+]](%struct.St* [[THIS_ONE]])
+// CK32: ret void
+
+// CK32: [[GLOBAL_TID_ADDR:%.+]] = alloca i32*
+// CK32: [[BOUND_TID_ADDR:%.+]] = alloca i32*
+// CK32: [[A_ADDR:%.+]] = alloca %struct.St
+// CK32: [[Y_ADDR:%.+]] = alloca i64
+// CK32: store i32* [[GLOBAL_TID:%.+]], i32** [[GLOBAL_TID_ADDR]]
+// CK32: store i32* %.bound_tid., i32** [[BOUND_TID_ADDR]]
+// CK32: store %struct.St* [[A_VAL]], %struct.St** [[A_ADDR]]{{.+}}
+// CK32: store i64 [[Y:%.+]], i64* [[Y_ADDR]]
+// CK32: [[ONE:%.+]] = load i32*, i32** [[GLOBAL_TID_ADDR]]
+// CK32: [[TWO:%.+]] = load i32, i32* [[ONE]]
+// CK32: [[THREE:%.+]] = call i32 @{{.+}} i32 [[TWO]])
+// CK32: [[FOUR:%.+]] = icmp ne i32 [[THREE]], 0
+// CK32: br i1 [[FOUR]], label [[IF_THEN:%.+]], label [[IF_END:%.+]]
+
+// CK32: [[A_1:%.+]] = getelementptr inbounds %struct.St, %struct.St* [[ZERO]], i32 0, i32 0
+// CK32: [[FIVE:%.+]] = load i32, i32* [[A_1]]
+// CK32: [[ADD:%.+]] = add nsw i32 [[FIVE]], 1
+// CK32: store i32 [[ADD]], i32* [[A_1]]
+// CK32: [[B:%.+]] = getelementptr inbounds %struct.St, %struct.St* [[ZERO]], i32 0, i32 1
+// CK32: [[SIX:%.+]] = load i32, i32* [[B]]
+// CK32: [[ADD_2:%.+]] = add nsw i32 [[SIX]], 1
+// CK32: store i32 [[ADD_2]], i32* [[B]]
+// CK32: [[SEVEN:%.+]] = load i32, i32* [[CONV]]
+// CK32: [[INC:%.+]] = add nsw i32 [[SEVEN]], 1
+// CK32: store i32 [[INC]], i32* [[CONV]]
+// CK32: [[EIGHT:%.+]] = load i32, i32* [[FUNC:@.+]]
+// CK32: [[INC_3:%.+]] = add nsw i32 [[EIGHT]], 1
+// CK32: store i32 [[INC_3]], i32* @{{.+}}
+// CK32: call void @{{.+}} i32 [[TWO]])
+// CK32: br label [[IF_END]]
+
+// CK32: [[DTOR]](%struct.St* [[THIS]])
+// CK32: [[THIS_ADDR]] = alloca %struct.St*
+// CK32: store %struct.St* [[THIS]], %struct.St** [[THIS_ADDR]]
+// CK32: [[THIS_ONE]] = load %struct.St*, %struct.St** [[THIS_ADDR]]
+// CK32: call void @_ZN2StD2Ev(%struct.St* [[THIS_ONE]])
+
+// CK32: [[THIS_ADDR]] = alloca %struct.St*
+// CK32: store %struct.St* [[THIS]], %struct.St** [[THIS_ADDR]]
+// CK32: [[THIS_ONE]] = load %struct.St*, %struct.St** [[THIS_ADDR]]
+// CK32: [[A_VAL]] = getelementptr inbounds %struct.St, %struct.St* [[THIS_ONE]], i32 0, i32 0
+// CK32: store i32 0, i32* [[A_VAL]]
+// CK32: [[B_VAL:%.+]] = getelementptr inbounds %struct.St, %struct.St* [[THIS_ONE]], i32 0, i32 1
+// CK32: store i32 0, i32* [[B_VAL]]
+// CK32: ret void
+
+// CK32: [[THIS_ADDR:%.+]] = alloca %struct.St*
+// CK32: store %struct.St* %this, %struct.St** [[THIS_ADDR]]
+// CK32: [[THIS_ONE]] = load %struct.St*, %struct.St** [[THIS_ADDR]]
+
+#endif
+
 #ifdef CK4
 ///==========================================================================///
 // RUN: %clang_cc1 -DCK4 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s --check-prefix CK4
diff --git a/clang/test/OpenMP/parallel_master_default_messages.cpp b/clang/test/OpenMP/parallel_master_default_messages.cpp
index 557cba5aa322a..39f78ea53ae16 100644
--- a/clang/test/OpenMP/parallel_master_default_messages.cpp
+++ b/clang/test/OpenMP/parallel_master_default_messages.cpp
@@ -2,20 +2,29 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
 #pragma omp parallel master default // expected-error {{expected '(' after 'default'}}
   {
-#pragma omp parallel master default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp parallel master default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
     {
-#pragma omp parallel master default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel master default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
       {
 #pragma omp parallel master default(none // expected-error {{expected ')'}} expected-note {{to match this '('}}
         {
 #pragma omp parallel master default(shared), default(shared) // expected-error {{directive '#pragma omp parallel master' cannot contain more than one 'default' clause}}
           {
-#pragma omp parallel master default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel master default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
             {
               foo();
             }
@@ -37,5 +46,14 @@ int main(int argc, char **argv) {
       ++argc;  // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
     }
   }
+
+#ifdef OMP51
+#pragma omp parallel master default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/parallel_sections_default_messages.cpp b/clang/test/OpenMP/parallel_sections_default_messages.cpp
index d6a10fe56b344..cfa95445fb536 100644
--- a/clang/test/OpenMP/parallel_sections_default_messages.cpp
+++ b/clang/test/OpenMP/parallel_sections_default_messages.cpp
@@ -7,15 +7,15 @@ void foo();
 int main(int argc, char **argv) {
 #pragma omp parallel sections default // expected-error {{expected '(' after 'default'}}
   {
-#pragma omp parallel sections default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp parallel sections default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
     {
-#pragma omp parallel sections default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel sections default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
       {
 #pragma omp parallel sections default(none // expected-error {{expected ')'}} expected-note {{to match this '('}}
         {
 #pragma omp parallel sections default(shared), default(shared) // expected-error {{directive '#pragma omp parallel sections' cannot contain more than one 'default' clause}}
           {
-#pragma omp parallel sections default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp parallel sections default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
             {
               foo();
             }
diff --git a/clang/test/OpenMP/target_parallel_default_messages.cpp b/clang/test/OpenMP/target_parallel_default_messages.cpp
index 0691cdf37e4eb..c8f68659438fe 100644
--- a/clang/test/OpenMP/target_parallel_default_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_default_messages.cpp
@@ -2,20 +2,29 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   #pragma omp target parallel default // expected-error {{expected '(' after 'default'}}
   foo();
-  #pragma omp target parallel default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target parallel default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   foo();
-  #pragma omp target parallel default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target parallel default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   foo();
   #pragma omp target parallel default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
   foo();
   #pragma omp target parallel default (shared), default(shared) // expected-error {{directive '#pragma omp target parallel' cannot contain more than one 'default' clause}}
   foo();
-  #pragma omp target parallel default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target parallel default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   foo();
 
   #pragma omp target parallel default(none) // expected-note {{explicit data sharing attribute requested here}}
@@ -28,5 +37,14 @@ int main(int argc, char **argv) {
   #pragma omp target parallel default(none) // expected-note {{explicit data sharing attribute requested here}}
   #pragma omp parallel default(shared)
   ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+#ifndef OMP51
+#pragma omp target parallel default(firstprivate) // expected-error {{data-sharing attribute 'firstprivate' in 'default' clause requires OpenMP version 5.1 or above}}
+  {
+    ++x;
+    ++y;
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/target_parallel_for_default_messages.cpp b/clang/test/OpenMP/target_parallel_for_default_messages.cpp
index fc6ba43138d76..4a3aae68e0865 100644
--- a/clang/test/OpenMP/target_parallel_for_default_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_default_messages.cpp
@@ -2,17 +2,26 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -DOMP51 -ferror-limit 100 -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -DOMP51 -ferror-limit 100 -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   int i;
 #pragma omp target parallel for default // expected-error {{expected '(' after 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp target parallel for default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target parallel for default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp target parallel for default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target parallel for default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target parallel for default(none // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{explicit data sharing attribute requested here}}
@@ -21,7 +30,7 @@ int main(int argc, char **argv) {
 #pragma omp target parallel for default(shared), default(shared) // expected-error {{directive '#pragma omp target parallel for' cannot contain more than one 'default' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp target parallel for default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target parallel for default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 
@@ -34,5 +43,13 @@ int main(int argc, char **argv) {
   for (i = 0; i < argc; ++i) // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
     foo();
 
+#ifndef OMP51
+#pragma omp target parallel for default(firstprivate) // expected-error {{data-sharing attribute 'firstprivate' in 'default' clause requires OpenMP version 5.1 or above}}
+  for (i = 0; i < argc; ++i) {
+    ++x;
+    ++y;
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/target_parallel_for_simd_default_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_default_messages.cpp
index daa93b9c9050b..48489309ef037 100644
--- a/clang/test/OpenMP/target_parallel_for_simd_default_messages.cpp
+++ b/clang/test/OpenMP/target_parallel_for_simd_default_messages.cpp
@@ -2,17 +2,26 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   int i;
 #pragma omp target parallel for simd default // expected-error {{expected '(' after 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp target parallel for simd default( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target parallel for simd default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp target parallel for simd default() // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target parallel for simd default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 #pragma omp target parallel for simd default(none // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-note {{explicit data sharing attribute requested here}}
@@ -21,7 +30,7 @@ int main(int argc, char **argv) {
 #pragma omp target parallel for simd default(shared), default(shared) // expected-error {{directive '#pragma omp target parallel for simd' cannot contain more than one 'default' clause}}
   for (i = 0; i < argc; ++i)
     foo();
-#pragma omp target parallel for simd default(x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target parallel for simd default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (i = 0; i < argc; ++i)
     foo();
 
@@ -34,5 +43,13 @@ int main(int argc, char **argv) {
   for (i = 0; i < argc; ++i) // expected-error {{variable 'i' must have explicitly specified data sharing attributes}} expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
     foo();
 
+#ifndef OMP51
+#pragma omp target parallel for simd default(firstprivate) // expected-error {{data-sharing attribute 'firstprivate' in 'default' clause requires OpenMP version 5.1 or above}}
+  for (int i = 0; i < argc; i++) {
+    ++x;
+    ++y;
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/target_teams_default_messages.cpp b/clang/test/OpenMP/target_teams_default_messages.cpp
index 21fa8270ef6a7..85c417f8f9853 100644
--- a/clang/test/OpenMP/target_teams_default_messages.cpp
+++ b/clang/test/OpenMP/target_teams_default_messages.cpp
@@ -2,20 +2,29 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
 #pragma omp target teams default // expected-error {{expected '(' after 'default'}}
   foo();
-#pragma omp target teams default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target teams default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   foo();
-#pragma omp target teams default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target teams default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   foo();
 #pragma omp target teams default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
   foo();
 #pragma omp target teams default (shared), default(shared) // expected-error {{directive '#pragma omp target teams' cannot contain more than one 'default' clause}}
   foo();
-#pragma omp target teams default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target teams default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   foo();
 
 #pragma omp target teams default(none) // expected-note {{explicit data sharing attribute requested here}}
@@ -24,5 +33,14 @@ int main(int argc, char **argv) {
 #pragma omp target teams default(none) // expected-note {{explicit data sharing attribute requested here}}
 #pragma omp parallel default(shared)
   ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+#ifndef OMP51
+#pragma omp target teams default(firstprivate) // expected-error {{data-sharing attribute 'firstprivate' in 'default' clause requires OpenMP version 5.1 or above}}
+  {
+    ++x;
+    ++y;
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/target_teams_distribute_default_messages.cpp b/clang/test/OpenMP/target_teams_distribute_default_messages.cpp
index fd834e7cba32c..a490ad61385ff 100644
--- a/clang/test/OpenMP/target_teams_distribute_default_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_default_messages.cpp
@@ -2,24 +2,41 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -DOMP51 %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=51 -DOMP51 %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   #pragma omp target teams distribute default // expected-error {{expected '(' after 'default'}}
   for (int i=0; i<200; i++) foo();
-  #pragma omp target teams distribute default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target teams distribute default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
-  #pragma omp target teams distribute default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target teams distribute default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target teams distribute default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target teams distribute default (shared), default(shared) // expected-error {{directive '#pragma omp target teams distribute' cannot contain more than one 'default' clause}}
   for (int i=0; i<200; i++) foo();
-  #pragma omp target teams distribute default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target teams distribute default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 
   #pragma omp target teams distribute default(none) // expected-note {{explicit data sharing attribute requested here}}
   for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
 
+#ifndef OMP51
+#pragma omp target teams distribute default(firstprivate) // expected-error {{data-sharing attribute 'firstprivate' in 'default' clause requires OpenMP version 5.1 or above}}
+  for (int i = 0; i < 200; i++) {
+    ++x;
+    ++y;
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp
index 00e0704a6ccac..2fe7931369618 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_default_messages.cpp
@@ -2,24 +2,41 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
 #pragma omp target teams distribute parallel for default // expected-error {{expected '(' after 'default'}}
   for (int i=0; i<200; i++) foo();
- #pragma omp target teams distribute parallel for default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target teams distribute parallel for default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
-#pragma omp target teams distribute parallel for default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target teams distribute parallel for default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 #pragma omp target teams distribute parallel for default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
 #pragma omp target teams distribute parallel for default (shared), default(shared) // expected-error {{directive '#pragma omp target teams distribute parallel for' cannot contain more than one 'default' clause}}
   for (int i=0; i<200; i++) foo();
-#pragma omp target teams distribute parallel for default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target teams distribute parallel for default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 
 #pragma omp target teams distribute parallel for default(none) // expected-note {{explicit data sharing attribute requested here}}
   for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
 
+#ifndef OMP51
+#pragma omp target teams distribute parallel for default(firstprivate) // expected-error {{data-sharing attribute 'firstprivate' in 'default' clause requires OpenMP version 5.1 or above}}
+  for (int i = 0; i < 200; i++) {
+    ++x;
+    ++y;
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp
index 7c46c964d2ec3..e5ff856222501 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_default_messages.cpp
@@ -2,16 +2,25 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
 #pragma omp target teams distribute parallel for simd default // expected-error {{expected '(' after 'default'}}
   for (int i=0; i<200; i++) foo();
 
-#pragma omp target teams distribute parallel for simd default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp target teams distribute parallel for simd default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
 
-#pragma omp target teams distribute parallel for simd default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target teams distribute parallel for simd default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 
 #pragma omp target teams distribute parallel for simd default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
@@ -20,11 +29,19 @@ int main(int argc, char **argv) {
 #pragma omp target teams distribute parallel for simd default (shared), default(shared) // expected-error {{directive '#pragma omp target teams distribute parallel for simd' cannot contain more than one 'default' clause}}
   for (int i=0; i<200; i++) foo();
 
-#pragma omp target teams distribute parallel for simd default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp target teams distribute parallel for simd default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 
 #pragma omp target teams distribute parallel for simd default(none) // expected-note {{explicit data sharing attribute requested here}}
   for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
 
+#ifndef OMP51
+#pragma omp target teams distribute parallel for simd default(firstprivate) // expected-error {{data-sharing attribute 'firstprivate' in 'default' clause requires OpenMP version 5.1 or above}}
+  for (int i = 0; i < argc; ++i) {
+    ++x;
+    ++y;
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/task_default_messages.cpp b/clang/test/OpenMP/task_default_messages.cpp
index 4826c253aa043..8b6809ee05d56 100644
--- a/clang/test/OpenMP/task_default_messages.cpp
+++ b/clang/test/OpenMP/task_default_messages.cpp
@@ -2,15 +2,24 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -ferror-limit 100 -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -ferror-limit 100 -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
 #pragma omp task default                          // expected-error {{expected '(' after 'default'}}
-#pragma omp task default(                         // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
-#pragma omp task default()                        // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp task default(                         // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp task default()                        // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
 #pragma omp task default(none                     // expected-error {{expected ')'}} expected-note {{to match this '('}}
 #pragma omp task default(shared), default(shared) // expected-error {{directive '#pragma omp task' cannot contain more than one 'default' clause}}
-#pragma omp task default(x)                       // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp task default(x)                       // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   foo();
 
 #pragma omp task default(none) // expected-note {{explicit data sharing attribute requested here}}
@@ -19,5 +28,13 @@ int main(int argc, char **argv) {
 #pragma omp task default(none) // expected-note {{explicit data sharing attribute requested here}}
 #pragma omp task default(shared)
   ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+#ifdef OMP51
+#pragma omp task default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
   return 0;
 }
diff --git a/clang/test/OpenMP/task_messages.cpp b/clang/test/OpenMP/task_messages.cpp
index 8b3183e0bd93e..13cbfb6c45693 100644
--- a/clang/test/OpenMP/task_messages.cpp
+++ b/clang/test/OpenMP/task_messages.cpp
@@ -4,6 +4,9 @@
 // RUN: %clang_cc1 -verify=expected,omp45 -fopenmp-version=45 -fopenmp-simd -ferror-limit 200 -std=c++11 -o - %s -Wuninitialized
 // RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=50 -fopenmp-simd -ferror-limit 200 -std=c++11 -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=51 -DOMP51 -fopenmp -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized
+// RUN: %clang_cc1 -verify=expected,omp50 -fopenmp-version=51 -DOMP51 -fopenmp-simd -ferror-limit 100 -std=c++11 -o - %s -Wuninitialized
+
 void xxx(int argc) {
   int x; // expected-note {{initialize the variable 'x' to silence this warning}}
 #pragma omp task
@@ -16,6 +19,10 @@ void foo() {
 }
 
 typedef unsigned long omp_event_handle_t;
+namespace {
+static int y = 0;
+}
+static int x = 0;
 
 #pragma omp task // expected-error {{unexpected OpenMP directive '#pragma omp task'}}
 
@@ -52,6 +59,15 @@ int foo() {
 #pragma omp task default(none) // expected-note 2 {{explicit data sharing attribute requested here}}
 #pragma omp task default(shared)
   ++a; // expected-error 2 {{variable 'a' must have explicitly specified data sharing attributes}}
+#ifdef OMP51
+#pragma omp task default(firstprivate) // expected-note 4 {{explicit data sharing attribute requested here}}
+#pragma omp task
+  {
+    ++x; // expected-error 2 {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error 2 {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
 #pragma omp task default(none) // expected-note 2 {{explicit data sharing attribute requested here}}
 #pragma omp task
   // expected-error@+1 {{calling a private constructor of class 'S'}}
diff --git a/clang/test/OpenMP/teams_default_messages.cpp b/clang/test/OpenMP/teams_default_messages.cpp
index a025050406000..b117ef4948a0f 100644
--- a/clang/test/OpenMP/teams_default_messages.cpp
+++ b/clang/test/OpenMP/teams_default_messages.cpp
@@ -2,17 +2,26 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd -o - %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp -o - %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd -o - %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   #pragma omp target
   #pragma omp teams default // expected-error {{expected '(' after 'default'}}
   foo();
   #pragma omp target
-  #pragma omp teams default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp teams default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   foo();
   #pragma omp target
-  #pragma omp teams default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   foo();
   #pragma omp target
   #pragma omp teams default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
@@ -21,7 +30,7 @@ int main(int argc, char **argv) {
   #pragma omp teams default (shared), default(shared) // expected-error {{directive '#pragma omp teams' cannot contain more than one 'default' clause}}
   foo();
   #pragma omp target
-  #pragma omp teams default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   foo();
 
   #pragma omp target
@@ -32,5 +41,14 @@ int main(int argc, char **argv) {
   #pragma omp teams default(none) // expected-note {{explicit data sharing attribute requested here}}
   #pragma omp parallel default(shared)
   ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
+
+#ifdef OMP51
+#pragma omp target
+#pragma omp teams default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
   return 0;
 }
diff --git a/clang/test/OpenMP/teams_distribute_default_messages.cpp b/clang/test/OpenMP/teams_distribute_default_messages.cpp
index 7f000208303b7..1d5fd40c53a6b 100644
--- a/clang/test/OpenMP/teams_distribute_default_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_default_messages.cpp
@@ -2,17 +2,26 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   #pragma omp target
   #pragma omp teams distribute default // expected-error {{expected '(' after 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp teams distribute default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams distribute default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
   #pragma omp teams distribute default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
@@ -21,12 +30,21 @@ int main(int argc, char **argv) {
   #pragma omp teams distribute default (shared), default(shared) // expected-error {{directive '#pragma omp teams distribute' cannot contain more than one 'default' clause}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams distribute default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 
   #pragma omp target
   #pragma omp teams distribute default(none) // expected-note {{explicit data sharing attribute requested here}}
   for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
 
+#ifdef OMP51
+#pragma omp target
+#pragma omp teams distribute default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  for (int i = 0; i < 200; i++) {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp
index 2c46623985070..3a414543be806 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_default_messages.cpp
@@ -2,17 +2,26 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp %s -Wuninitialized
+
+// RUN: %clang_cc1 -verify -fopenmp-version=51 -DOMP51 -fopenmp-simd %s -Wuninitialized
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   #pragma omp target
   #pragma omp teams distribute parallel for default // expected-error {{expected '(' after 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute parallel for default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp teams distribute parallel for default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute parallel for default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams distribute parallel for default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
   #pragma omp teams distribute parallel for default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
@@ -21,12 +30,21 @@ int main(int argc, char **argv) {
   #pragma omp teams distribute parallel for default (shared), default(shared) // expected-error {{directive '#pragma omp teams distribute parallel for' cannot contain more than one 'default' clause}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute parallel for default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams distribute parallel for default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 
   #pragma omp target
   #pragma omp teams distribute parallel for default(none) // expected-note {{explicit data sharing attribute requested here}}
   for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
 
+#ifdef OMP51
+#pragma omp target
+#pragma omp teams distribute parallel for default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  for (int i = 0; i < 200; i++) {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp
index 93017a8233ffe..ce7f35b479592 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_default_messages.cpp
@@ -2,17 +2,26 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized -fopenmp-version=51 -DOMP51
+
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized -fopenmp-version=51 -DOMP51
+
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   #pragma omp target
   #pragma omp teams distribute parallel for simd default // expected-error {{expected '(' after 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute parallel for simd default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp teams distribute parallel for simd default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute parallel for simd default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams distribute parallel for simd default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
   #pragma omp teams distribute parallel for simd default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
@@ -21,12 +30,20 @@ int main(int argc, char **argv) {
   #pragma omp teams distribute parallel for simd default (shared), default(shared) // expected-error {{directive '#pragma omp teams distribute parallel for simd' cannot contain more than one 'default' clause}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute parallel for simd default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams distribute parallel for simd default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 
   #pragma omp target
   #pragma omp teams distribute parallel for simd default(none) // expected-note {{explicit data sharing attribute requested here}}
   for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
 
+#ifdef OpenMP51
+#pragma omp teams distribute parallel for default(firstprivate) // expected-note 2 {{explicit data sharing attribute requested here}}
+  for (int i = 0; i < 200; i++) {
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+  }
+#endif
+
   return 0;
 }
diff --git a/clang/test/OpenMP/teams_distribute_simd_default_messages.cpp b/clang/test/OpenMP/teams_distribute_simd_default_messages.cpp
index 2775210ae048f..11f5d1cd1fc8f 100644
--- a/clang/test/OpenMP/teams_distribute_simd_default_messages.cpp
+++ b/clang/test/OpenMP/teams_distribute_simd_default_messages.cpp
@@ -1,18 +1,23 @@
-// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp %s -Wuninitialized -fopenmp-version=51
 
-// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
+// RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized -fopenmp-version=51
 
 void foo();
 
+namespace {
+static int y = 0;
+}
+static int x = 0;
+
 int main(int argc, char **argv) {
   #pragma omp target
   #pragma omp teams distribute simd default // expected-error {{expected '(' after 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute simd default ( // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp teams distribute simd default( // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}} expected-error {{expected ')'}} expected-note {{to match this '('}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute simd default () // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams distribute simd default() // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
   #pragma omp teams distribute simd default (none // expected-error {{expected ')'}} expected-note {{to match this '('}}
@@ -21,12 +26,22 @@ int main(int argc, char **argv) {
   #pragma omp teams distribute simd default (shared), default(shared) // expected-error {{directive '#pragma omp teams distribute simd' cannot contain more than one 'default' clause}}
   for (int i=0; i<200; i++) foo();
   #pragma omp target
-  #pragma omp teams distribute simd default (x) // expected-error {{expected 'none' or 'shared' in OpenMP clause 'default'}}
+#pragma omp teams distribute simd default(x) // expected-error {{expected 'none', 'shared' or 'firstprivate' in OpenMP clause 'default'}}
   for (int i=0; i<200; i++) foo();
 
   #pragma omp target
   #pragma omp teams distribute simd default(none) // expected-note {{explicit data sharing attribute requested here}}
   for (int i=0; i<200; i++) ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}}
 
+#pragma omp target
+#pragma omp teams distribute simd default(firstprivate) // expected-note {{explicit data sharing attribute requested here}}
+  for (int i = 0; i < 200; i++)
+    ++x; // expected-error {{variable 'x' must have explicitly specified data sharing attributes}}
+
+#pragma omp target
+#pragma omp teams distribute simd default(firstprivate) // expected-note {{explicit data sharing attribute requested here}}
+  for (int i = 0; i < 200; i++)
+    ++y; // expected-error {{variable 'y' must have explicitly specified data sharing attributes}}
+
   return 0;
 }
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index aeb4fd098d224..687908043a8d3 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -103,9 +103,9 @@ TEST(IsExpandedFromMacro, ShouldMatchFromCommandLine) {
   StringRef input = R"cc(
     void Test() { FOUR_PLUS_FOUR; }
   )cc";
-  EXPECT_TRUE(matchesConditionally(input,
-                                   binaryOperator(isExpandedFromMacro("FOUR_PLUS_FOUR")),
-                                   true, {"-std=c++11", "-DFOUR_PLUS_FOUR=4+4"}));
+  EXPECT_TRUE(matchesConditionally(
+      input, binaryOperator(isExpandedFromMacro("FOUR_PLUS_FOUR")), true,
+      {"-std=c++11", "-DFOUR_PLUS_FOUR=4+4"}));
 }
 
 TEST(IsExpandedFromMacro, ShouldNotMatchBeginOnly) {
@@ -143,31 +143,31 @@ TEST(IsExpandedFromMacro, ShouldNotMatchDifferentInstances) {
 }
 
 TEST(AllOf, AllOverloadsWork) {
-  const char Program[] =
-      "struct T { };"
-      "int f(int, T*, int, int);"
-      "void g(int x) { T t; f(x, &t, 3, 4); }";
-  EXPECT_TRUE(matches(Program,
-      callExpr(allOf(callee(functionDecl(hasName("f"))),
-                     hasArgument(0, declRefExpr(to(varDecl())))))));
-  EXPECT_TRUE(matches(Program,
-      callExpr(allOf(callee(functionDecl(hasName("f"))),
-                     hasArgument(0, declRefExpr(to(varDecl()))),
-                     hasArgument(1, hasType(pointsTo(
-                                        recordDecl(hasName("T")))))))));
-  EXPECT_TRUE(matches(Program,
-      callExpr(allOf(callee(functionDecl(hasName("f"))),
-                     hasArgument(0, declRefExpr(to(varDecl()))),
-                     hasArgument(1, hasType(pointsTo(
-                                        recordDecl(hasName("T"))))),
-                     hasArgument(2, integerLiteral(equals(3)))))));
-  EXPECT_TRUE(matches(Program,
-      callExpr(allOf(callee(functionDecl(hasName("f"))),
-                     hasArgument(0, declRefExpr(to(varDecl()))),
-                     hasArgument(1, hasType(pointsTo(
-                                        recordDecl(hasName("T"))))),
-                     hasArgument(2, integerLiteral(equals(3))),
-                     hasArgument(3, integerLiteral(equals(4)))))));
+  const char Program[] = "struct T { };"
+                         "int f(int, T*, int, int);"
+                         "void g(int x) { T t; f(x, &t, 3, 4); }";
+  EXPECT_TRUE(matches(
+      Program, callExpr(allOf(callee(functionDecl(hasName("f"))),
+                              hasArgument(0, declRefExpr(to(varDecl())))))));
+  EXPECT_TRUE(matches(
+      Program,
+      callExpr(
+          allOf(callee(functionDecl(hasName("f"))),
+                hasArgument(0, declRefExpr(to(varDecl()))),
+                hasArgument(1, hasType(pointsTo(recordDecl(hasName("T")))))))));
+  EXPECT_TRUE(matches(
+      Program, callExpr(allOf(
+                   callee(functionDecl(hasName("f"))),
+                   hasArgument(0, declRefExpr(to(varDecl()))),
+                   hasArgument(1, hasType(pointsTo(recordDecl(hasName("T"))))),
+                   hasArgument(2, integerLiteral(equals(3)))))));
+  EXPECT_TRUE(matches(
+      Program, callExpr(allOf(
+                   callee(functionDecl(hasName("f"))),
+                   hasArgument(0, declRefExpr(to(varDecl()))),
+                   hasArgument(1, hasType(pointsTo(recordDecl(hasName("T"))))),
+                   hasArgument(2, integerLiteral(equals(3))),
+                   hasArgument(3, integerLiteral(equals(4)))))));
 }
 
 TEST(DeclarationMatcher, MatchHas) {
@@ -176,127 +176,103 @@ TEST(DeclarationMatcher, MatchHas) {
   EXPECT_TRUE(matches("class X {};", HasClassX));
 
   DeclarationMatcher YHasClassX =
-    recordDecl(hasName("Y"), has(recordDecl(hasName("X"))));
+      recordDecl(hasName("Y"), has(recordDecl(hasName("X"))));
   EXPECT_TRUE(matches("class Y { class X {}; };", YHasClassX));
   EXPECT_TRUE(notMatches("class X {};", YHasClassX));
-  EXPECT_TRUE(
-    notMatches("class Y { class Z { class X {}; }; };", YHasClassX));
+  EXPECT_TRUE(notMatches("class Y { class Z { class X {}; }; };", YHasClassX));
 }
 
 TEST(DeclarationMatcher, MatchHasRecursiveAllOf) {
   DeclarationMatcher Recursive =
-    recordDecl(
-      has(recordDecl(
-        has(recordDecl(hasName("X"))),
-        has(recordDecl(hasName("Y"))),
-        hasName("Z"))),
-      has(recordDecl(
-        has(recordDecl(hasName("A"))),
-        has(recordDecl(hasName("B"))),
-        hasName("C"))),
-      hasName("F"));
-
-  EXPECT_TRUE(matches(
-    "class F {"
-      "  class Z {"
-      "    class X {};"
-      "    class Y {};"
-      "  };"
-      "  class C {"
-      "    class A {};"
-      "    class B {};"
-      "  };"
-      "};", Recursive));
-
-  EXPECT_TRUE(matches(
-    "class F {"
-      "  class Z {"
-      "    class A {};"
-      "    class X {};"
-      "    class Y {};"
-      "  };"
-      "  class C {"
-      "    class X {};"
-      "    class A {};"
-      "    class B {};"
-      "  };"
-      "};", Recursive));
-
-  EXPECT_TRUE(matches(
-    "class O1 {"
-      "  class O2 {"
-      "    class F {"
-      "      class Z {"
-      "        class A {};"
-      "        class X {};"
-      "        class Y {};"
-      "      };"
-      "      class C {"
-      "        class X {};"
-      "        class A {};"
-      "        class B {};"
-      "      };"
-      "    };"
-      "  };"
-      "};", Recursive));
+      recordDecl(has(recordDecl(has(recordDecl(hasName("X"))),
+                                has(recordDecl(hasName("Y"))), hasName("Z"))),
+                 has(recordDecl(has(recordDecl(hasName("A"))),
+                                has(recordDecl(hasName("B"))), hasName("C"))),
+                 hasName("F"));
+
+  EXPECT_TRUE(matches("class F {"
+                      "  class Z {"
+                      "    class X {};"
+                      "    class Y {};"
+                      "  };"
+                      "  class C {"
+                      "    class A {};"
+                      "    class B {};"
+                      "  };"
+                      "};",
+                      Recursive));
+
+  EXPECT_TRUE(matches("class F {"
+                      "  class Z {"
+                      "    class A {};"
+                      "    class X {};"
+                      "    class Y {};"
+                      "  };"
+                      "  class C {"
+                      "    class X {};"
+                      "    class A {};"
+                      "    class B {};"
+                      "  };"
+                      "};",
+                      Recursive));
+
+  EXPECT_TRUE(matches("class O1 {"
+                      "  class O2 {"
+                      "    class F {"
+                      "      class Z {"
+                      "        class A {};"
+                      "        class X {};"
+                      "        class Y {};"
+                      "      };"
+                      "      class C {"
+                      "        class X {};"
+                      "        class A {};"
+                      "        class B {};"
+                      "      };"
+                      "    };"
+                      "  };"
+                      "};",
+                      Recursive));
 }
 
 TEST(DeclarationMatcher, MatchHasRecursiveAnyOf) {
-  DeclarationMatcher Recursive =
-    recordDecl(
-      anyOf(
-        has(recordDecl(
-          anyOf(
-            has(recordDecl(
-              hasName("X"))),
-            has(recordDecl(
-              hasName("Y"))),
-            hasName("Z")))),
-        has(recordDecl(
-          anyOf(
-            hasName("C"),
-            has(recordDecl(
-              hasName("A"))),
-            has(recordDecl(
-              hasName("B")))))),
-        hasName("F")));
+  DeclarationMatcher Recursive = recordDecl(
+      anyOf(has(recordDecl(anyOf(has(recordDecl(hasName("X"))),
+                                 has(recordDecl(hasName("Y"))), hasName("Z")))),
+            has(recordDecl(anyOf(hasName("C"), has(recordDecl(hasName("A"))),
+                                 has(recordDecl(hasName("B")))))),
+            hasName("F")));
 
   EXPECT_TRUE(matches("class F {};", Recursive));
   EXPECT_TRUE(matches("class Z {};", Recursive));
   EXPECT_TRUE(matches("class C {};", Recursive));
   EXPECT_TRUE(matches("class M { class N { class X {}; }; };", Recursive));
   EXPECT_TRUE(matches("class M { class N { class B {}; }; };", Recursive));
-  EXPECT_TRUE(
-    matches("class O1 { class O2 {"
-              "  class M { class N { class B {}; }; }; "
-              "}; };", Recursive));
+  EXPECT_TRUE(matches("class O1 { class O2 {"
+                      "  class M { class N { class B {}; }; }; "
+                      "}; };",
+                      Recursive));
 }
 
 TEST(DeclarationMatcher, MatchNot) {
   DeclarationMatcher NotClassX =
-    cxxRecordDecl(
-      isDerivedFrom("Y"),
-      unless(hasName("X")));
+      cxxRecordDecl(isDerivedFrom("Y"), unless(hasName("X")));
   EXPECT_TRUE(notMatches("", NotClassX));
   EXPECT_TRUE(notMatches("class Y {};", NotClassX));
   EXPECT_TRUE(matches("class Y {}; class Z : public Y {};", NotClassX));
   EXPECT_TRUE(notMatches("class Y {}; class X : public Y {};", NotClassX));
   EXPECT_TRUE(
-    notMatches("class Y {}; class Z {}; class X : public Y {};",
-               NotClassX));
+      notMatches("class Y {}; class Z {}; class X : public Y {};", NotClassX));
 
   DeclarationMatcher ClassXHasNotClassY =
-    recordDecl(
-      hasName("X"),
-      has(recordDecl(hasName("Z"))),
-      unless(
-        has(recordDecl(hasName("Y")))));
+      recordDecl(hasName("X"), has(recordDecl(hasName("Z"))),
+                 unless(has(recordDecl(hasName("Y")))));
   EXPECT_TRUE(matches("class X { class Z {}; };", ClassXHasNotClassY));
-  EXPECT_TRUE(notMatches("class X { class Y {}; class Z {}; };",
-                         ClassXHasNotClassY));
+  EXPECT_TRUE(
+      notMatches("class X { class Y {}; class Z {}; };", ClassXHasNotClassY));
 
   DeclarationMatcher NamedNotRecord =
-    namedDecl(hasName("Foo"), unless(recordDecl()));
+      namedDecl(hasName("Foo"), unless(recordDecl()));
   EXPECT_TRUE(matches("void Foo(){}", NamedNotRecord));
   EXPECT_TRUE(notMatches("struct Foo {};", NamedNotRecord));
 }
@@ -318,67 +294,61 @@ TEST(CastExpression, HasCastKind) {
 
 TEST(DeclarationMatcher, HasDescendant) {
   DeclarationMatcher ZDescendantClassX =
-    recordDecl(
-      hasDescendant(recordDecl(hasName("X"))),
-      hasName("Z"));
+      recordDecl(hasDescendant(recordDecl(hasName("X"))), hasName("Z"));
   EXPECT_TRUE(matches("class Z { class X {}; };", ZDescendantClassX));
   EXPECT_TRUE(
-    matches("class Z { class Y { class X {}; }; };", ZDescendantClassX));
+      matches("class Z { class Y { class X {}; }; };", ZDescendantClassX));
+  EXPECT_TRUE(matches("class Z { class A { class Y { class X {}; }; }; };",
+                      ZDescendantClassX));
   EXPECT_TRUE(
-    matches("class Z { class A { class Y { class X {}; }; }; };",
-            ZDescendantClassX));
-  EXPECT_TRUE(
-    matches("class Z { class A { class B { class Y { class X {}; }; }; }; };",
-            ZDescendantClassX));
+      matches("class Z { class A { class B { class Y { class X {}; }; }; }; };",
+              ZDescendantClassX));
   EXPECT_TRUE(notMatches("class Z {};", ZDescendantClassX));
 
-  DeclarationMatcher ZDescendantClassXHasClassY =
-    recordDecl(
-      hasDescendant(recordDecl(has(recordDecl(hasName("Y"))),
-                               hasName("X"))),
+  DeclarationMatcher ZDescendantClassXHasClassY = recordDecl(
+      hasDescendant(recordDecl(has(recordDecl(hasName("Y"))), hasName("X"))),
       hasName("Z"));
   EXPECT_TRUE(matches("class Z { class X { class Y {}; }; };",
                       ZDescendantClassXHasClassY));
   EXPECT_TRUE(
-    matches("class Z { class A { class B { class X { class Y {}; }; }; }; };",
-            ZDescendantClassXHasClassY));
-  EXPECT_TRUE(notMatches(
-    "class Z {"
-      "  class A {"
-      "    class B {"
-      "      class X {"
-      "        class C {"
-      "          class Y {};"
-      "        };"
-      "      };"
-      "    }; "
-      "  };"
-      "};", ZDescendantClassXHasClassY));
+      matches("class Z { class A { class B { class X { class Y {}; }; }; }; };",
+              ZDescendantClassXHasClassY));
+  EXPECT_TRUE(notMatches("class Z {"
+                         "  class A {"
+                         "    class B {"
+                         "      class X {"
+                         "        class C {"
+                         "          class Y {};"
+                         "        };"
+                         "      };"
+                         "    }; "
+                         "  };"
+                         "};",
+                         ZDescendantClassXHasClassY));
 
   DeclarationMatcher ZDescendantClassXDescendantClassY =
-    recordDecl(
-      hasDescendant(recordDecl(hasDescendant(recordDecl(hasName("Y"))),
-                               hasName("X"))),
-      hasName("Z"));
-  EXPECT_TRUE(
-    matches("class Z { class A { class X { class B { class Y {}; }; }; }; };",
-            ZDescendantClassXDescendantClassY));
-  EXPECT_TRUE(matches(
-    "class Z {"
-      "  class A {"
-      "    class X {"
-      "      class B {"
-      "        class Y {};"
-      "      };"
-      "      class Y {};"
-      "    };"
-      "  };"
-      "};", ZDescendantClassXDescendantClassY));
+      recordDecl(hasDescendant(recordDecl(
+                     hasDescendant(recordDecl(hasName("Y"))), hasName("X"))),
+                 hasName("Z"));
+  EXPECT_TRUE(
+      matches("class Z { class A { class X { class B { class Y {}; }; }; }; };",
+              ZDescendantClassXDescendantClassY));
+  EXPECT_TRUE(matches("class Z {"
+                      "  class A {"
+                      "    class X {"
+                      "      class B {"
+                      "        class Y {};"
+                      "      };"
+                      "      class Y {};"
+                      "    };"
+                      "  };"
+                      "};",
+                      ZDescendantClassXDescendantClassY));
 }
 
 TEST(DeclarationMatcher, HasDescendantMemoization) {
   DeclarationMatcher CannotMemoize =
-    decl(hasDescendant(typeLoc().bind("x")), has(decl()));
+      decl(hasDescendant(typeLoc().bind("x")), has(decl()));
   EXPECT_TRUE(matches("void f() { int i; }", CannotMemoize));
 }
 
@@ -401,39 +371,36 @@ TEST(DeclarationMatcher, HasAncestorMemoization) {
   // That node can't be memoized so we have to check for it before trying to put
   // it on the cache.
   DeclarationMatcher CannotMemoize = classTemplateSpecializationDecl(
-    hasAnyTemplateArgument(templateArgument().bind("targ")),
-    forEach(fieldDecl(hasAncestor(forStmt()))));
+      hasAnyTemplateArgument(templateArgument().bind("targ")),
+      forEach(fieldDecl(hasAncestor(forStmt()))));
 
   EXPECT_TRUE(notMatches("template  struct S;"
-                           "template <> struct S{ int i; int j; };",
+                         "template <> struct S{ int i; int j; };",
                          CannotMemoize));
 }
 
 TEST(DeclarationMatcher, HasAttr) {
   EXPECT_TRUE(matches("struct __attribute__((warn_unused)) X {};",
                       decl(hasAttr(clang::attr::WarnUnused))));
-  EXPECT_FALSE(matches("struct X {};",
-                       decl(hasAttr(clang::attr::WarnUnused))));
+  EXPECT_FALSE(matches("struct X {};", decl(hasAttr(clang::attr::WarnUnused))));
 }
 
-
 TEST(DeclarationMatcher, MatchAnyOf) {
   DeclarationMatcher YOrZDerivedFromX = cxxRecordDecl(
-    anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
+      anyOf(hasName("Y"), allOf(isDerivedFrom("X"), hasName("Z"))));
   EXPECT_TRUE(matches("class X {}; class Z : public X {};", YOrZDerivedFromX));
   EXPECT_TRUE(matches("class Y {};", YOrZDerivedFromX));
   EXPECT_TRUE(
-    notMatches("class X {}; class W : public X {};", YOrZDerivedFromX));
+      notMatches("class X {}; class W : public X {};", YOrZDerivedFromX));
   EXPECT_TRUE(notMatches("class Z {};", YOrZDerivedFromX));
 
   DeclarationMatcher XOrYOrZOrU =
-    recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U")));
+      recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U")));
   EXPECT_TRUE(matches("class X {};", XOrYOrZOrU));
   EXPECT_TRUE(notMatches("class V {};", XOrYOrZOrU));
 
-  DeclarationMatcher XOrYOrZOrUOrV =
-    recordDecl(anyOf(hasName("X"), hasName("Y"), hasName("Z"), hasName("U"),
-                     hasName("V")));
+  DeclarationMatcher XOrYOrZOrUOrV = recordDecl(anyOf(
+      hasName("X"), hasName("Y"), hasName("Z"), hasName("U"), hasName("V")));
   EXPECT_TRUE(matches("class X {};", XOrYOrZOrUOrV));
   EXPECT_TRUE(matches("class Y {};", XOrYOrZOrUOrV));
   EXPECT_TRUE(matches("class Z {};", XOrYOrZOrUOrV));
@@ -447,8 +414,8 @@ TEST(DeclarationMatcher, MatchAnyOf) {
   EXPECT_TRUE(notMatches("int F() { return 1; }", MixedTypes));
 
   EXPECT_TRUE(
-    matches("void f() try { } catch (int) { } catch (...) { }",
-            cxxCatchStmt(anyOf(hasDescendant(varDecl()), isCatchAll()))));
+      matches("void f() try { } catch (int) { } catch (...) { }",
+              cxxCatchStmt(anyOf(hasDescendant(varDecl()), isCatchAll()))));
 }
 
 TEST(DeclarationMatcher, ClassIsDerived) {
@@ -460,19 +427,17 @@ TEST(DeclarationMatcher, ClassIsDerived) {
   EXPECT_TRUE(notMatches("class Y;", IsDerivedFromX));
   EXPECT_TRUE(notMatches("", IsDerivedFromX));
   EXPECT_TRUE(matches("class X {}; template class Y : Y, X {};",
-    IsDerivedFromX));
+                      IsDerivedFromX));
   EXPECT_TRUE(matches("class X {}; template class Y : X, Y {};",
-    IsDerivedFromX));
+                      IsDerivedFromX));
 
-  DeclarationMatcher IsZDerivedFromX = cxxRecordDecl(hasName("Z"),
-    isDerivedFrom("X"));
-  EXPECT_TRUE(
-    matches(
-      "class X {};"
-      "template class Y : Y {};"
-      "template<> class Y<0> : X {};"
-      "class Z : Y<1> {};",
-      IsZDerivedFromX));
+  DeclarationMatcher IsZDerivedFromX =
+      cxxRecordDecl(hasName("Z"), isDerivedFrom("X"));
+  EXPECT_TRUE(matches("class X {};"
+                      "template class Y : Y {};"
+                      "template<> class Y<0> : X {};"
+                      "class Z : Y<1> {};",
+                      IsZDerivedFromX));
 
   DeclarationMatcher IsDirectlyDerivedFromX =
       cxxRecordDecl(isDirectlyDerivedFrom("X"));
@@ -493,145 +458,138 @@ TEST(DeclarationMatcher, ClassIsDerived) {
   EXPECT_TRUE(notMatches("", IsAX));
 
   DeclarationMatcher ZIsDerivedFromX =
-    cxxRecordDecl(hasName("Z"), isDerivedFrom("X"));
+      cxxRecordDecl(hasName("Z"), isDerivedFrom("X"));
   DeclarationMatcher ZIsDirectlyDerivedFromX =
       cxxRecordDecl(hasName("Z"), isDirectlyDerivedFrom("X"));
   EXPECT_TRUE(
-    matches("class X {}; class Y : public X {}; class Z : public Y {};",
-            ZIsDerivedFromX));
+      matches("class X {}; class Y : public X {}; class Z : public Y {};",
+              ZIsDerivedFromX));
   EXPECT_TRUE(
       notMatches("class X {}; class Y : public X {}; class Z : public Y {};",
                  ZIsDirectlyDerivedFromX));
-  EXPECT_TRUE(
-    matches("class X {};"
-              "template class Y : public X {};"
-              "class Z : public Y {};", ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class X {};"
+                      "template class Y : public X {};"
+                      "class Z : public Y {};",
+                      ZIsDerivedFromX));
   EXPECT_TRUE(notMatches("class X {};"
                          "template class Y : public X {};"
                          "class Z : public Y {};",
                          ZIsDirectlyDerivedFromX));
   EXPECT_TRUE(matches("class X {}; template class Z : public X {};",
                       ZIsDerivedFromX));
+  EXPECT_TRUE(matches("template class X {}; "
+                      "template class Z : public X {};",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(matches("template class X {}; "
+                      "template class Z : public X {};",
+                      ZIsDerivedFromX));
   EXPECT_TRUE(
-    matches("template class X {}; "
-              "template class Z : public X {};",
-            ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("template class X {}; "
-              "template class Z : public X {};",
-            ZIsDerivedFromX));
-  EXPECT_TRUE(
-    notMatches("template class A { class Z : public X {}; };",
-               ZIsDerivedFromX));
+      notMatches("template class A { class Z : public X {}; };",
+                 ZIsDerivedFromX));
   EXPECT_TRUE(
-    matches("template class A { public: class Z : public X {}; }; "
-              "class X{}; void y() { A::Z z; }", ZIsDerivedFromX));
+      matches("template class A { public: class Z : public X {}; }; "
+              "class X{}; void y() { A::Z z; }",
+              ZIsDerivedFromX));
   EXPECT_TRUE(
-    matches("template  class X {}; "
+      matches("template  class X {}; "
               "template class A { class Z : public X {}; };",
-            ZIsDerivedFromX));
-  EXPECT_TRUE(
-    notMatches("template class X> class A { "
-                 "  class Z : public X {}; };", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("template class X> class A { "
-              "  public: class Z : public X {}; }; "
-              "template class X {}; void y() { A::Z z; }",
-            ZIsDerivedFromX));
-  EXPECT_TRUE(
-    notMatches("template class A { class Z : public X::D {}; };",
-               ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("template class A { public: "
-              "  class Z : public X::D {}; }; "
-              "class Y { public: class X {}; typedef X D; }; "
-              "void y() { A::Z z; }", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("class X {}; typedef X Y; class Z : public Y {};",
-            ZIsDerivedFromX));
+              ZIsDerivedFromX));
+  EXPECT_TRUE(notMatches("template class X> class A { "
+                         "  class Z : public X {}; };",
+                         ZIsDerivedFromX));
+  EXPECT_TRUE(matches("template class X> class A { "
+                      "  public: class Z : public X {}; }; "
+                      "template class X {}; void y() { A::Z z; }",
+                      ZIsDerivedFromX));
   EXPECT_TRUE(
-    matches("template class Y { typedef typename T::U X; "
-              "  class Z : public X {}; };", ZIsDerivedFromX));
-  EXPECT_TRUE(matches("class X {}; class Z : public ::X {};",
+      notMatches("template class A { class Z : public X::D {}; };",
+                 ZIsDerivedFromX));
+  EXPECT_TRUE(matches("template class A { public: "
+                      "  class Z : public X::D {}; }; "
+                      "class Y { public: class X {}; typedef X D; }; "
+                      "void y() { A::Z z; }",
                       ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class X {}; typedef X Y; class Z : public Y {};",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(matches("template class Y { typedef typename T::U X; "
+                      "  class Z : public X {}; };",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class X {}; class Z : public ::X {};", ZIsDerivedFromX));
   EXPECT_TRUE(
-    notMatches("template class X {}; "
+      notMatches("template class X {}; "
                  "template class A { class Z : public X::D {}; };",
-               ZIsDerivedFromX));
+                 ZIsDerivedFromX));
   EXPECT_TRUE(
-    matches("template class X { public: typedef X D; }; "
+      matches("template class X { public: typedef X D; }; "
               "template class A { public: "
               "  class Z : public X::D {}; }; void y() { A::Z z; }",
-            ZIsDerivedFromX));
+              ZIsDerivedFromX));
   EXPECT_TRUE(
-    notMatches("template class A { class Z : public X::D::E {}; };",
-               ZIsDerivedFromX));
+      notMatches("template class A { class Z : public X::D::E {}; };",
+                 ZIsDerivedFromX));
   EXPECT_TRUE(
-    matches("class X {}; typedef X V; typedef V W; class Z : public W {};",
-            ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("class X {}; class Y : public X {}; "
-              "typedef Y V; typedef V W; class Z : public W {};",
-            ZIsDerivedFromX));
+      matches("class X {}; typedef X V; typedef V W; class Z : public W {};",
+              ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class X {}; class Y : public X {}; "
+                      "typedef Y V; typedef V W; class Z : public W {};",
+                      ZIsDerivedFromX));
   EXPECT_TRUE(notMatches("class X {}; class Y : public X {}; "
                          "typedef Y V; typedef V W; class Z : public W {};",
                          ZIsDirectlyDerivedFromX));
   EXPECT_TRUE(
-    matches("template class X {}; "
+      matches("template class X {}; "
               "template class A { class Z : public X {}; };",
-            ZIsDerivedFromX));
+              ZIsDerivedFromX));
   EXPECT_TRUE(
-    notMatches("template class D { typedef X A; typedef A B; "
+      notMatches("template class D { typedef X A; typedef A B; "
                  "  typedef B C; class Z : public C {}; };",
-               ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("class X {}; typedef X A; typedef A B; "
-              "class Z : public B {};", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("class X {}; typedef X A; typedef A B; typedef B C; "
-              "class Z : public C {};", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("class U {}; typedef U X; typedef X V; "
-              "class Z : public V {};", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("class Base {}; typedef Base X; "
-              "class Z : public Base {};", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("class Base {}; typedef Base Base2; typedef Base2 X; "
-              "class Z : public Base {};", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    notMatches("class Base {}; class Base2 {}; typedef Base2 X; "
-                 "class Z : public Base {};", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    matches("class A {}; typedef A X; typedef A Y; "
-              "class Z : public Y {};", ZIsDerivedFromX));
-  EXPECT_TRUE(
-    notMatches("template  class Z;"
-                 "template <> class Z {};"
-                 "template  class Z : public Z {};",
-               IsDerivedFromX));
-  EXPECT_TRUE(
-    matches("template  class X;"
-              "template <> class X {};"
-              "template  class X : public X {};",
-            IsDerivedFromX));
-  EXPECT_TRUE(matches(
-    "class X {};"
-      "template  class Z;"
-      "template <> class Z {};"
-      "template  class Z : public Z, public X {};",
-    ZIsDerivedFromX));
-  EXPECT_TRUE(
-    notMatches("template struct X;"
+                 ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class X {}; typedef X A; typedef A B; "
+                      "class Z : public B {};",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class X {}; typedef X A; typedef A B; typedef B C; "
+                      "class Z : public C {};",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class U {}; typedef U X; typedef X V; "
+                      "class Z : public V {};",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class Base {}; typedef Base X; "
+                      "class Z : public Base {};",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class Base {}; typedef Base Base2; typedef Base2 X; "
+                      "class Z : public Base {};",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(notMatches("class Base {}; class Base2 {}; typedef Base2 X; "
+                         "class Z : public Base {};",
+                         ZIsDerivedFromX));
+  EXPECT_TRUE(matches("class A {}; typedef A X; typedef A Y; "
+                      "class Z : public Y {};",
+                      ZIsDerivedFromX));
+  EXPECT_TRUE(notMatches("template  class Z;"
+                         "template <> class Z {};"
+                         "template  class Z : public Z {};",
+                         IsDerivedFromX));
+  EXPECT_TRUE(matches("template  class X;"
+                      "template <> class X {};"
+                      "template  class X : public X {};",
+                      IsDerivedFromX));
+  EXPECT_TRUE(
+      matches("class X {};"
+              "template  class Z;"
+              "template <> class Z {};"
+              "template  class Z : public Z, public X {};",
+              ZIsDerivedFromX));
+  EXPECT_TRUE(
+      notMatches("template struct X;"
                  "template struct X : public X {};",
-               cxxRecordDecl(isDerivedFrom(recordDecl(hasName("Some"))))));
+                 cxxRecordDecl(isDerivedFrom(recordDecl(hasName("Some"))))));
   EXPECT_TRUE(matches(
-    "struct A {};"
+      "struct A {};"
       "template struct X;"
       "template struct X : public X {};"
       "template<> struct X<0> : public A {};"
       "struct B : public X<42> {};",
-    cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A"))))));
+      cxxRecordDecl(hasName("B"), isDerivedFrom(recordDecl(hasName("A"))))));
   EXPECT_TRUE(notMatches(
       "struct A {};"
       "template struct X;"
@@ -645,7 +603,7 @@ TEST(DeclarationMatcher, ClassIsDerived) {
   // get rid of the Variable(...) matching and match the right template
   // declarations directly.
   const char *RecursiveTemplateOneParameter =
-    "class Base1 {}; class Base2 {};"
+      "class Base1 {}; class Base2 {};"
       "template  class Z;"
       "template <> class Z : public Base1 {};"
       "template <> class Z : public Base2 {};"
@@ -654,21 +612,21 @@ TEST(DeclarationMatcher, ClassIsDerived) {
       "template  class Z : public Z, public Z {};"
       "void f() { Z z_float; Z z_double; Z z_char; }";
   EXPECT_TRUE(matches(
-    RecursiveTemplateOneParameter,
-    varDecl(hasName("z_float"),
-            hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
+      RecursiveTemplateOneParameter,
+      varDecl(hasName("z_float"),
+              hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
   EXPECT_TRUE(notMatches(
-    RecursiveTemplateOneParameter,
-    varDecl(hasName("z_float"),
-            hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
-  EXPECT_TRUE(matches(
-    RecursiveTemplateOneParameter,
-    varDecl(hasName("z_char"),
-            hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"),
-                                                 isDerivedFrom("Base2")))))));
+      RecursiveTemplateOneParameter,
+      varDecl(hasName("z_float"),
+              hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
+  EXPECT_TRUE(
+      matches(RecursiveTemplateOneParameter,
+              varDecl(hasName("z_char"),
+                      hasInitializer(hasType(cxxRecordDecl(
+                          isDerivedFrom("Base1"), isDerivedFrom("Base2")))))));
 
   const char *RecursiveTemplateTwoParameters =
-    "class Base1 {}; class Base2 {};"
+      "class Base1 {}; class Base2 {};"
       "template  class Z;"
       "template  class Z : public Base1 {};"
       "template  class Z : public Base2 {};"
@@ -679,34 +637,31 @@ TEST(DeclarationMatcher, ClassIsDerived) {
       "void f() { Z z_float; Z z_double; "
       "           Z z_char; }";
   EXPECT_TRUE(matches(
-    RecursiveTemplateTwoParameters,
-    varDecl(hasName("z_float"),
-            hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
-  EXPECT_TRUE(notMatches(
-    RecursiveTemplateTwoParameters,
-    varDecl(hasName("z_float"),
-            hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
-  EXPECT_TRUE(matches(
-    RecursiveTemplateTwoParameters,
-    varDecl(hasName("z_char"),
-            hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1"),
-                                                 isDerivedFrom("Base2")))))));
-  EXPECT_TRUE(matches(
-    "namespace ns { class X {}; class Y : public X {}; }",
-    cxxRecordDecl(isDerivedFrom("::ns::X"))));
+      RecursiveTemplateTwoParameters,
+      varDecl(hasName("z_float"),
+              hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base1")))))));
   EXPECT_TRUE(notMatches(
-    "class X {}; class Y : public X {};",
-    cxxRecordDecl(isDerivedFrom("::ns::X"))));
+      RecursiveTemplateTwoParameters,
+      varDecl(hasName("z_float"),
+              hasInitializer(hasType(cxxRecordDecl(isDerivedFrom("Base2")))))));
+  EXPECT_TRUE(
+      matches(RecursiveTemplateTwoParameters,
+              varDecl(hasName("z_char"),
+                      hasInitializer(hasType(cxxRecordDecl(
+                          isDerivedFrom("Base1"), isDerivedFrom("Base2")))))));
+  EXPECT_TRUE(matches("namespace ns { class X {}; class Y : public X {}; }",
+                      cxxRecordDecl(isDerivedFrom("::ns::X"))));
+  EXPECT_TRUE(notMatches("class X {}; class Y : public X {};",
+                         cxxRecordDecl(isDerivedFrom("::ns::X"))));
 
   EXPECT_TRUE(matches(
-    "class X {}; class Y : public X {};",
-    cxxRecordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
+      "class X {}; class Y : public X {};",
+      cxxRecordDecl(isDerivedFrom(recordDecl(hasName("X")).bind("test")))));
 
-  EXPECT_TRUE(matches(
-    "template class X {};"
-      "template using Z = X;"
-      "template  class Y : Z {};",
-    cxxRecordDecl(isDerivedFrom(namedDecl(hasName("X"))))));
+  EXPECT_TRUE(matches("template class X {};"
+                      "template using Z = X;"
+                      "template  class Y : Z {};",
+                      cxxRecordDecl(isDerivedFrom(namedDecl(hasName("X"))))));
 }
 
 TEST(DeclarationMatcher, IsDerivedFromEmptyName) {
@@ -737,24 +692,24 @@ TEST(DeclarationMatcher, ObjCClassIsDerived) {
 
   DeclarationMatcher IsDirectlyDerivedFromX =
       objcInterfaceDecl(isDirectlyDerivedFrom("X"));
-  EXPECT_TRUE(
-      matchesObjC("@interface X @end @interface Y : X @end", IsDirectlyDerivedFromX));
+  EXPECT_TRUE(matchesObjC("@interface X @end @interface Y : X @end",
+                          IsDirectlyDerivedFromX));
   EXPECT_TRUE(matchesObjC(
       "@interface X @end @interface Y<__covariant ObjectType> : X @end",
       IsDirectlyDerivedFromX));
   EXPECT_TRUE(matchesObjC(
       "@interface X @end @compatibility_alias Y X; @interface Z : Y @end",
       IsDirectlyDerivedFromX));
-  EXPECT_TRUE(matchesObjC(
-      "@interface X @end typedef X Y; @interface Z : Y @end",
-      IsDirectlyDerivedFromX));
+  EXPECT_TRUE(
+      matchesObjC("@interface X @end typedef X Y; @interface Z : Y @end",
+                  IsDirectlyDerivedFromX));
   EXPECT_TRUE(notMatchesObjC("@interface X @end", IsDirectlyDerivedFromX));
   EXPECT_TRUE(notMatchesObjC("@class X;", IsDirectlyDerivedFromX));
   EXPECT_TRUE(notMatchesObjC("@class Y;", IsDirectlyDerivedFromX));
   EXPECT_TRUE(notMatchesObjC("@interface X @end @compatibility_alias Y X;",
                              IsDirectlyDerivedFromX));
-  EXPECT_TRUE(notMatchesObjC("@interface X @end typedef X Y;",
-                             IsDirectlyDerivedFromX));
+  EXPECT_TRUE(
+      notMatchesObjC("@interface X @end typedef X Y;", IsDirectlyDerivedFromX));
 
   DeclarationMatcher IsAX = objcInterfaceDecl(isSameOrDerivedFrom("X"));
   EXPECT_TRUE(matchesObjC("@interface X @end @interface Y : X @end", IsAX));
@@ -775,9 +730,9 @@ TEST(DeclarationMatcher, ObjCClassIsDerived) {
                           ZIsDerivedFromX));
   EXPECT_TRUE(matchesObjC(
       "@interface X @end typedef X Y; @interface Z : Y @end", ZIsDerivedFromX));
-  EXPECT_TRUE(matchesObjC(
-      "@interface X @end typedef X Y; @interface Z : Y @end",
-      ZIsDirectlyDerivedFromX));
+  EXPECT_TRUE(
+      matchesObjC("@interface X @end typedef X Y; @interface Z : Y @end",
+                  ZIsDirectlyDerivedFromX));
   EXPECT_TRUE(matchesObjC(
       "@interface A @end typedef A X; typedef A Y; @interface Z : Y @end",
       ZIsDerivedFromX));
@@ -798,27 +753,33 @@ TEST(DeclarationMatcher, ObjCClassIsDerived) {
       ZIsDirectlyDerivedFromX));
   EXPECT_TRUE(matchesObjC(
       "@interface A @end @compatibility_alias X A; @compatibility_alias Y A;"
-      "@interface Z : Y @end", ZIsDerivedFromX));
+      "@interface Z : Y @end",
+      ZIsDerivedFromX));
   EXPECT_TRUE(matchesObjC(
       "@interface A @end @compatibility_alias X A; @compatibility_alias Y A;"
-      "@interface Z : Y @end", ZIsDirectlyDerivedFromX));
-  EXPECT_TRUE(matchesObjC(
-      "@interface Y @end typedef Y X; @interface Z : X @end", ZIsDerivedFromX));
-  EXPECT_TRUE(matchesObjC(
-      "@interface Y @end typedef Y X; @interface Z : X @end",
+      "@interface Z : Y @end",
       ZIsDirectlyDerivedFromX));
   EXPECT_TRUE(matchesObjC(
-      "@interface A @end @compatibility_alias Y A; typedef Y X;"
-      "@interface Z : A @end", ZIsDerivedFromX));
-  EXPECT_TRUE(matchesObjC(
-      "@interface A @end @compatibility_alias Y A; typedef Y X;"
-      "@interface Z : A @end", ZIsDirectlyDerivedFromX));
-  EXPECT_TRUE(matchesObjC(
-      "@interface A @end typedef A Y; @compatibility_alias X Y;"
-      "@interface Z : A @end", ZIsDerivedFromX));
-  EXPECT_TRUE(matchesObjC(
-      "@interface A @end typedef A Y; @compatibility_alias X Y;"
-      "@interface Z : A @end", ZIsDirectlyDerivedFromX));
+      "@interface Y @end typedef Y X; @interface Z : X @end", ZIsDerivedFromX));
+  EXPECT_TRUE(
+      matchesObjC("@interface Y @end typedef Y X; @interface Z : X @end",
+                  ZIsDirectlyDerivedFromX));
+  EXPECT_TRUE(
+      matchesObjC("@interface A @end @compatibility_alias Y A; typedef Y X;"
+                  "@interface Z : A @end",
+                  ZIsDerivedFromX));
+  EXPECT_TRUE(
+      matchesObjC("@interface A @end @compatibility_alias Y A; typedef Y X;"
+                  "@interface Z : A @end",
+                  ZIsDirectlyDerivedFromX));
+  EXPECT_TRUE(
+      matchesObjC("@interface A @end typedef A Y; @compatibility_alias X Y;"
+                  "@interface Z : A @end",
+                  ZIsDerivedFromX));
+  EXPECT_TRUE(
+      matchesObjC("@interface A @end typedef A Y; @compatibility_alias X Y;"
+                  "@interface Z : A @end",
+                  ZIsDirectlyDerivedFromX));
 }
 
 TEST(DeclarationMatcher, IsLambda) {
@@ -830,42 +791,41 @@ TEST(DeclarationMatcher, IsLambda) {
 TEST(Matcher, BindMatchedNodes) {
   DeclarationMatcher ClassX = has(recordDecl(hasName("::X")).bind("x"));
 
-  EXPECT_TRUE(matchAndVerifyResultTrue("class X {};",
-                                       ClassX, std::make_unique>("x")));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class X {};", ClassX,
+      std::make_unique>("x")));
 
-  EXPECT_TRUE(matchAndVerifyResultFalse("class X {};",
-                                        ClassX, std::make_unique>("other-id")));
+  EXPECT_TRUE(matchAndVerifyResultFalse(
+      "class X {};", ClassX,
+      std::make_unique>("other-id")));
 
   TypeMatcher TypeAHasClassB = hasDeclaration(
-    recordDecl(hasName("A"), has(recordDecl(hasName("B")).bind("b"))));
+      recordDecl(hasName("A"), has(recordDecl(hasName("B")).bind("b"))));
 
-  EXPECT_TRUE(matchAndVerifyResultTrue("class A { public: A *a; class B {}; };",
-                                       TypeAHasClassB,
-                                       std::make_unique>("b")));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class A { public: A *a; class B {}; };", TypeAHasClassB,
+      std::make_unique>("b")));
 
   StatementMatcher MethodX =
-    callExpr(callee(cxxMethodDecl(hasName("x")))).bind("x");
+      callExpr(callee(cxxMethodDecl(hasName("x")))).bind("x");
 
-  EXPECT_TRUE(matchAndVerifyResultTrue("class A { void x() { x(); } };",
-                                       MethodX,
-                                       std::make_unique>("x")));
+  EXPECT_TRUE(matchAndVerifyResultTrue(
+      "class A { void x() { x(); } };", MethodX,
+      std::make_unique>("x")));
 }
 
 TEST(Matcher, BindTheSameNameInAlternatives) {
   StatementMatcher matcher = anyOf(
-    binaryOperator(hasOperatorName("+"),
-                   hasLHS(expr().bind("x")),
-                   hasRHS(integerLiteral(equals(0)))),
-    binaryOperator(hasOperatorName("+"),
-                   hasLHS(integerLiteral(equals(0))),
-                   hasRHS(expr().bind("x"))));
+      binaryOperator(hasOperatorName("+"), hasLHS(expr().bind("x")),
+                     hasRHS(integerLiteral(equals(0)))),
+      binaryOperator(hasOperatorName("+"), hasLHS(integerLiteral(equals(0))),
+                     hasRHS(expr().bind("x"))));
 
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    // The first branch of the matcher binds x to 0 but then fails.
-    // The second branch binds x to f() and succeeds.
-    "int f() { return 0 + f(); }",
-    matcher,
-    std::make_unique>("x")));
+      // The first branch of the matcher binds x to 0 but then fails.
+      // The second branch binds x to f() and succeeds.
+      "int f() { return 0 + f(); }", matcher,
+      std::make_unique>("x")));
 }
 
 TEST(Matcher, BindsIDForMemoizedResults) {
@@ -873,48 +833,48 @@ TEST(Matcher, BindsIDForMemoizedResults) {
   // kick in.
   DeclarationMatcher ClassX = recordDecl(hasName("X")).bind("x");
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "class A { class B { class X {}; }; };",
-    DeclarationMatcher(anyOf(
-      recordDecl(hasName("A"), hasDescendant(ClassX)),
-      recordDecl(hasName("B"), hasDescendant(ClassX)))),
-    std::make_unique>("x", 2)));
+      "class A { class B { class X {}; }; };",
+      DeclarationMatcher(
+          anyOf(recordDecl(hasName("A"), hasDescendant(ClassX)),
+                recordDecl(hasName("B"), hasDescendant(ClassX)))),
+      std::make_unique>("x", 2)));
 }
 
 TEST(HasType, MatchesAsString) {
   EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z() {Y* y; y->x(); }",
-            cxxMemberCallExpr(on(hasType(asString("class Y *"))))));
+      matches("class Y { public: void x(); }; void z() {Y* y; y->x(); }",
+              cxxMemberCallExpr(on(hasType(asString("class Y *"))))));
   EXPECT_TRUE(
-    matches("class X { void x(int x) {} };",
-            cxxMethodDecl(hasParameter(0, hasType(asString("int"))))));
+      matches("class X { void x(int x) {} };",
+              cxxMethodDecl(hasParameter(0, hasType(asString("int"))))));
   EXPECT_TRUE(matches("namespace ns { struct A {}; }  struct B { ns::A a; };",
                       fieldDecl(hasType(asString("ns::A")))));
-  EXPECT_TRUE(matches("namespace { struct A {}; }  struct B { A a; };",
-                      fieldDecl(hasType(asString("struct (anonymous namespace)::A")))));
+  EXPECT_TRUE(
+      matches("namespace { struct A {}; }  struct B { A a; };",
+              fieldDecl(hasType(asString("struct (anonymous namespace)::A")))));
 }
 
 TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
   StatementMatcher OpCallAndAnd =
-    cxxOperatorCallExpr(hasOverloadedOperatorName("&&"));
+      cxxOperatorCallExpr(hasOverloadedOperatorName("&&"));
   EXPECT_TRUE(matches("class Y { }; "
-                        "bool operator&&(Y x, Y y) { return true; }; "
-                        "Y a; Y b; bool c = a && b;", OpCallAndAnd));
+                      "bool operator&&(Y x, Y y) { return true; }; "
+                      "Y a; Y b; bool c = a && b;",
+                      OpCallAndAnd));
   StatementMatcher OpCallLessLess =
-    cxxOperatorCallExpr(hasOverloadedOperatorName("<<"));
+      cxxOperatorCallExpr(hasOverloadedOperatorName("<<"));
   EXPECT_TRUE(notMatches("class Y { }; "
-                           "bool operator&&(Y x, Y y) { return true; }; "
-                           "Y a; Y b; bool c = a && b;",
+                         "bool operator&&(Y x, Y y) { return true; }; "
+                         "Y a; Y b; bool c = a && b;",
                          OpCallLessLess));
   StatementMatcher OpStarCall =
-    cxxOperatorCallExpr(hasOverloadedOperatorName("*"));
-  EXPECT_TRUE(matches("class Y; int operator*(Y &); void f(Y &y) { *y; }",
-                      OpStarCall));
+      cxxOperatorCallExpr(hasOverloadedOperatorName("*"));
+  EXPECT_TRUE(
+      matches("class Y; int operator*(Y &); void f(Y &y) { *y; }", OpStarCall));
   DeclarationMatcher ClassWithOpStar =
-    cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")));
-  EXPECT_TRUE(matches("class Y { int operator*(); };",
-                      ClassWithOpStar));
-  EXPECT_TRUE(notMatches("class Y { void myOperator(); };",
-                         ClassWithOpStar)) ;
+      cxxRecordDecl(hasMethod(hasOverloadedOperatorName("*")));
+  EXPECT_TRUE(matches("class Y { int operator*(); };", ClassWithOpStar));
+  EXPECT_TRUE(notMatches("class Y { void myOperator(); };", ClassWithOpStar));
   DeclarationMatcher AnyOpStar = functionDecl(hasOverloadedOperatorName("*"));
   EXPECT_TRUE(matches("class Y; int operator*(Y &);", AnyOpStar));
   EXPECT_TRUE(matches("class Y { int operator*(); };", AnyOpStar));
@@ -926,23 +886,22 @@ TEST(Matcher, HasOperatorNameForOverloadedOperatorCall) {
   EXPECT_TRUE(matches("class Y { Y operator&&(Y &); };", AnyAndOp));
 }
 
-
 TEST(Matcher, NestedOverloadedOperatorCalls) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "class Y { }; "
+      "class Y { }; "
       "Y& operator&&(Y& x, Y& y) { return x; }; "
       "Y a; Y b; Y c; Y d = a && b && c;",
-    cxxOperatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"),
-    std::make_unique>("x", 2)));
+      cxxOperatorCallExpr(hasOverloadedOperatorName("&&")).bind("x"),
+      std::make_unique>("x", 2)));
   EXPECT_TRUE(matches("class Y { }; "
-                        "Y& operator&&(Y& x, Y& y) { return x; }; "
-                        "Y a; Y b; Y c; Y d = a && b && c;",
+                      "Y& operator&&(Y& x, Y& y) { return x; }; "
+                      "Y a; Y b; Y c; Y d = a && b && c;",
                       cxxOperatorCallExpr(hasParent(cxxOperatorCallExpr()))));
   EXPECT_TRUE(
-    matches("class Y { }; "
+      matches("class Y { }; "
               "Y& operator&&(Y& x, Y& y) { return x; }; "
               "Y a; Y b; Y c; Y d = a && b && c;",
-            cxxOperatorCallExpr(hasDescendant(cxxOperatorCallExpr()))));
+              cxxOperatorCallExpr(hasDescendant(cxxOperatorCallExpr()))));
 }
 
 TEST(Matcher, VarDecl_Storage) {
@@ -971,9 +930,9 @@ TEST(Matcher, VarDecl_StorageDuration) {
 
   EXPECT_TRUE(matches(T, varDecl(hasName("x"), hasAutomaticStorageDuration())));
   EXPECT_TRUE(
-    notMatches(T, varDecl(hasName("y"), hasAutomaticStorageDuration())));
+      notMatches(T, varDecl(hasName("y"), hasAutomaticStorageDuration())));
   EXPECT_TRUE(
-    notMatches(T, varDecl(hasName("a"), hasAutomaticStorageDuration())));
+      notMatches(T, varDecl(hasName("a"), hasAutomaticStorageDuration())));
 
   EXPECT_TRUE(matches(T, varDecl(hasName("y"), hasStaticStorageDuration())));
   EXPECT_TRUE(matches(T, varDecl(hasName("a"), hasStaticStorageDuration())));
@@ -991,48 +950,48 @@ TEST(Matcher, VarDecl_StorageDuration) {
 }
 
 TEST(Matcher, FindsVarDeclInFunctionParameter) {
-  EXPECT_TRUE(matches(
-    "void f(int i) {}",
-    varDecl(hasName("i"))));
+  EXPECT_TRUE(matches("void f(int i) {}", varDecl(hasName("i"))));
 }
 
 TEST(UnaryExpressionOrTypeTraitExpression, MatchesCorrectType) {
-  EXPECT_TRUE(matches("void x() { int a = sizeof(a); }", sizeOfExpr(
-    hasArgumentOfType(asString("int")))));
-  EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }", sizeOfExpr(
-    hasArgumentOfType(asString("float")))));
+  EXPECT_TRUE(matches("void x() { int a = sizeof(a); }",
+                      sizeOfExpr(hasArgumentOfType(asString("int")))));
+  EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }",
+                         sizeOfExpr(hasArgumentOfType(asString("float")))));
   EXPECT_TRUE(matches(
-    "struct A {}; void x() { A a; int b = sizeof(a); }",
-    sizeOfExpr(hasArgumentOfType(hasDeclaration(recordDecl(hasName("A")))))));
-  EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }", sizeOfExpr(
-    hasArgumentOfType(hasDeclaration(recordDecl(hasName("string")))))));
+      "struct A {}; void x() { A a; int b = sizeof(a); }",
+      sizeOfExpr(hasArgumentOfType(hasDeclaration(recordDecl(hasName("A")))))));
+  EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }",
+                         sizeOfExpr(hasArgumentOfType(
+                             hasDeclaration(recordDecl(hasName("string")))))));
 }
 
 TEST(IsInteger, MatchesIntegers) {
   EXPECT_TRUE(matches("int i = 0;", varDecl(hasType(isInteger()))));
-  EXPECT_TRUE(matches(
-    "long long i = 0; void f(long long) { }; void g() {f(i);}",
-    callExpr(hasArgument(0, declRefExpr(
-      to(varDecl(hasType(isInteger()))))))));
+  EXPECT_TRUE(
+      matches("long long i = 0; void f(long long) { }; void g() {f(i);}",
+              callExpr(hasArgument(
+                  0, declRefExpr(to(varDecl(hasType(isInteger()))))))));
 }
 
 TEST(IsInteger, ReportsNoFalsePositives) {
   EXPECT_TRUE(notMatches("int *i;", varDecl(hasType(isInteger()))));
-  EXPECT_TRUE(notMatches("struct T {}; T t; void f(T *) { }; void g() {f(&t);}",
-                         callExpr(hasArgument(0, declRefExpr(
-                           to(varDecl(hasType(isInteger()))))))));
+  EXPECT_TRUE(
+      notMatches("struct T {}; T t; void f(T *) { }; void g() {f(&t);}",
+                 callExpr(hasArgument(
+                     0, declRefExpr(to(varDecl(hasType(isInteger()))))))));
 }
 
 TEST(IsSignedInteger, MatchesSignedIntegers) {
   EXPECT_TRUE(matches("int i = 0;", varDecl(hasType(isSignedInteger()))));
-  EXPECT_TRUE(notMatches("unsigned i = 0;",
-                         varDecl(hasType(isSignedInteger()))));
+  EXPECT_TRUE(
+      notMatches("unsigned i = 0;", varDecl(hasType(isSignedInteger()))));
 }
 
 TEST(IsUnsignedInteger, MatchesUnsignedIntegers) {
   EXPECT_TRUE(notMatches("int i = 0;", varDecl(hasType(isUnsignedInteger()))));
-  EXPECT_TRUE(matches("unsigned i = 0;",
-                      varDecl(hasType(isUnsignedInteger()))));
+  EXPECT_TRUE(
+      matches("unsigned i = 0;", varDecl(hasType(isUnsignedInteger()))));
 }
 
 TEST(IsAnyPointer, MatchesPointers) {
@@ -1059,8 +1018,8 @@ TEST(IsAnyCharacter, ReportsNoFalsePositives) {
 TEST(IsArrow, MatchesMemberVariablesViaArrow) {
   EXPECT_TRUE(matches("class Y { void x() { this->y; } int y; };",
                       memberExpr(isArrow())));
-  EXPECT_TRUE(matches("class Y { void x() { y; } int y; };",
-                      memberExpr(isArrow())));
+  EXPECT_TRUE(
+      matches("class Y { void x() { y; } int y; };", memberExpr(isArrow())));
   EXPECT_TRUE(notMatches("class Y { void x() { (*this).y; } int y; };",
                          memberExpr(isArrow())));
   EXPECT_TRUE(matches("template  class Y { void x() { this->m; } };",
@@ -1080,10 +1039,9 @@ TEST(IsArrow, MatchesStaticMemberVariablesViaArrow) {
 }
 
 TEST(IsArrow, MatchesMemberCallsViaArrow) {
-  EXPECT_TRUE(matches("class Y { void x() { this->x(); } };",
-                      memberExpr(isArrow())));
-  EXPECT_TRUE(matches("class Y { void x() { x(); } };",
-                      memberExpr(isArrow())));
+  EXPECT_TRUE(
+      matches("class Y { void x() { this->x(); } };", memberExpr(isArrow())));
+  EXPECT_TRUE(matches("class Y { void x() { x(); } };", memberExpr(isArrow())));
   EXPECT_TRUE(notMatches("class Y { void x() { Y y; y.x(); } };",
                          memberExpr(isArrow())));
   EXPECT_TRUE(
@@ -1128,20 +1086,18 @@ TEST(Matcher, ParameterCount) {
 }
 
 TEST(Matcher, References) {
-  DeclarationMatcher ReferenceClassX = varDecl(
-    hasType(references(recordDecl(hasName("X")))));
-  EXPECT_TRUE(matches("class X {}; void y(X y) { X &x = y; }",
-                      ReferenceClassX));
+  DeclarationMatcher ReferenceClassX =
+      varDecl(hasType(references(recordDecl(hasName("X")))));
   EXPECT_TRUE(
-    matches("class X {}; void y(X y) { const X &x = y; }", ReferenceClassX));
+      matches("class X {}; void y(X y) { X &x = y; }", ReferenceClassX));
+  EXPECT_TRUE(
+      matches("class X {}; void y(X y) { const X &x = y; }", ReferenceClassX));
   // The match here is on the implicit copy constructor code for
   // class X, not on code 'X x = y'.
+  EXPECT_TRUE(matches("class X {}; void y(X y) { X x = y; }", ReferenceClassX));
+  EXPECT_TRUE(notMatches("class X {}; extern X x;", ReferenceClassX));
   EXPECT_TRUE(
-    matches("class X {}; void y(X y) { X x = y; }", ReferenceClassX));
-  EXPECT_TRUE(
-    notMatches("class X {}; extern X x;", ReferenceClassX));
-  EXPECT_TRUE(
-    notMatches("class X {}; void y(X *y) { X *&x = y; }", ReferenceClassX));
+      notMatches("class X {}; void y(X *y) { X *&x = y; }", ReferenceClassX));
 }
 
 TEST(QualType, hasLocalQualifiers) {
@@ -1149,16 +1105,15 @@ TEST(QualType, hasLocalQualifiers) {
                          varDecl(hasType(hasLocalQualifiers()))));
   EXPECT_TRUE(matches("int *const j = nullptr;",
                       varDecl(hasType(hasLocalQualifiers()))));
-  EXPECT_TRUE(matches("int *volatile k;",
-                      varDecl(hasType(hasLocalQualifiers()))));
-  EXPECT_TRUE(notMatches("int m;",
-                         varDecl(hasType(hasLocalQualifiers()))));
+  EXPECT_TRUE(
+      matches("int *volatile k;", varDecl(hasType(hasLocalQualifiers()))));
+  EXPECT_TRUE(notMatches("int m;", varDecl(hasType(hasLocalQualifiers()))));
 }
 
 TEST(IsExternC, MatchesExternCFunctionDeclarations) {
   EXPECT_TRUE(matches("extern \"C\" void f() {}", functionDecl(isExternC())));
-  EXPECT_TRUE(matches("extern \"C\" { void f() {} }",
-                      functionDecl(isExternC())));
+  EXPECT_TRUE(
+      matches("extern \"C\" { void f() {} }", functionDecl(isExternC())));
   EXPECT_TRUE(notMatches("void f() {}", functionDecl(isExternC())));
 }
 
@@ -1186,7 +1141,7 @@ TEST(IsDefaulted, MatchesDefaultedFunctionDeclarations) {
 
 TEST(IsDeleted, MatchesDeletedFunctionDeclarations) {
   EXPECT_TRUE(
-    notMatches("void Func();", functionDecl(hasName("Func"), isDeleted())));
+      notMatches("void Func();", functionDecl(hasName("Func"), isDeleted())));
   EXPECT_TRUE(matches("void Func() = delete;",
                       functionDecl(hasName("Func"), isDeleted())));
 }
@@ -1195,14 +1150,15 @@ TEST(IsNoThrow, MatchesNoThrowFunctionDeclarations) {
   EXPECT_TRUE(notMatches("void f();", functionDecl(isNoThrow())));
   EXPECT_TRUE(notMatches("void f() throw(int);", functionDecl(isNoThrow())));
   EXPECT_TRUE(
-    notMatches("void f() noexcept(false);", functionDecl(isNoThrow())));
+      notMatches("void f() noexcept(false);", functionDecl(isNoThrow())));
   EXPECT_TRUE(matches("void f() throw();", functionDecl(isNoThrow())));
   EXPECT_TRUE(matches("void f() noexcept;", functionDecl(isNoThrow())));
 
   EXPECT_TRUE(notMatches("void f();", functionProtoType(isNoThrow())));
-  EXPECT_TRUE(notMatches("void f() throw(int);", functionProtoType(isNoThrow())));
   EXPECT_TRUE(
-    notMatches("void f() noexcept(false);", functionProtoType(isNoThrow())));
+      notMatches("void f() throw(int);", functionProtoType(isNoThrow())));
+  EXPECT_TRUE(
+      notMatches("void f() noexcept(false);", functionProtoType(isNoThrow())));
   EXPECT_TRUE(matches("void f() throw();", functionProtoType(isNoThrow())));
   EXPECT_TRUE(matches("void f() noexcept;", functionProtoType(isNoThrow())));
 }
@@ -1249,41 +1205,41 @@ TEST(hasInitStatement, MatchesRangeForInitializers) {
 
 TEST(TemplateArgumentCountIs, Matches) {
   EXPECT_TRUE(
-    matches("template struct C {}; C c;",
-            classTemplateSpecializationDecl(templateArgumentCountIs(1))));
+      matches("template struct C {}; C c;",
+              classTemplateSpecializationDecl(templateArgumentCountIs(1))));
   EXPECT_TRUE(
-    notMatches("template struct C {}; C c;",
-               classTemplateSpecializationDecl(templateArgumentCountIs(2))));
+      notMatches("template struct C {}; C c;",
+                 classTemplateSpecializationDecl(templateArgumentCountIs(2))));
 
   EXPECT_TRUE(matches("template struct C {}; C c;",
                       templateSpecializationType(templateArgumentCountIs(1))));
   EXPECT_TRUE(
-    notMatches("template struct C {}; C c;",
-               templateSpecializationType(templateArgumentCountIs(2))));
+      notMatches("template struct C {}; C c;",
+                 templateSpecializationType(templateArgumentCountIs(2))));
 }
 
 TEST(IsIntegral, Matches) {
-  EXPECT_TRUE(matches("template struct C {}; C<42> c;",
-                      classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(isIntegral()))));
+  EXPECT_TRUE(matches(
+      "template struct C {}; C<42> c;",
+      classTemplateSpecializationDecl(hasAnyTemplateArgument(isIntegral()))));
   EXPECT_TRUE(notMatches("template struct C {}; C c;",
                          classTemplateSpecializationDecl(hasAnyTemplateArgument(
-                           templateArgument(isIntegral())))));
+                             templateArgument(isIntegral())))));
 }
 
 TEST(EqualsIntegralValue, Matches) {
   EXPECT_TRUE(matches("template struct C {}; C<42> c;",
                       classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(equalsIntegralValue("42")))));
+                          hasAnyTemplateArgument(equalsIntegralValue("42")))));
   EXPECT_TRUE(matches("template struct C {}; C<-42> c;",
                       classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(equalsIntegralValue("-42")))));
+                          hasAnyTemplateArgument(equalsIntegralValue("-42")))));
   EXPECT_TRUE(matches("template struct C {}; C<-0042> c;",
                       classTemplateSpecializationDecl(
-                        hasAnyTemplateArgument(equalsIntegralValue("-34")))));
+                          hasAnyTemplateArgument(equalsIntegralValue("-34")))));
   EXPECT_TRUE(notMatches("template struct C {}; C<42> c;",
                          classTemplateSpecializationDecl(hasAnyTemplateArgument(
-                           equalsIntegralValue("0042")))));
+                             equalsIntegralValue("0042")))));
 }
 
 TEST(Matcher, MatchesAccessSpecDecls) {
@@ -1304,7 +1260,7 @@ TEST(Matcher, MatchesFinal) {
                       cxxMethodDecl(isFinal())));
   EXPECT_TRUE(notMatches("class X {};", cxxRecordDecl(isFinal())));
   EXPECT_TRUE(
-    notMatches("class X { virtual void f(); };", cxxMethodDecl(isFinal())));
+      notMatches("class X { virtual void f(); };", cxxMethodDecl(isFinal())));
 }
 
 TEST(Matcher, MatchesVirtualMethod) {
@@ -1315,12 +1271,12 @@ TEST(Matcher, MatchesVirtualMethod) {
 
 TEST(Matcher, MatchesVirtualAsWrittenMethod) {
   EXPECT_TRUE(matches("class A { virtual int f(); };"
-                        "class B : public A { int f(); };",
+                      "class B : public A { int f(); };",
                       cxxMethodDecl(isVirtualAsWritten(), hasName("::A::f"))));
   EXPECT_TRUE(
-    notMatches("class A { virtual int f(); };"
+      notMatches("class A { virtual int f(); };"
                  "class B : public A { int f(); };",
-               cxxMethodDecl(isVirtualAsWritten(), hasName("::B::f"))));
+                 cxxMethodDecl(isVirtualAsWritten(), hasName("::B::f"))));
 }
 
 TEST(Matcher, MatchesPureMethod) {
@@ -1358,26 +1314,26 @@ TEST(Matcher, MatchesMoveAssignmentOperator) {
 
 TEST(Matcher, MatchesConstMethod) {
   EXPECT_TRUE(
-    matches("struct A { void foo() const; };", cxxMethodDecl(isConst())));
+      matches("struct A { void foo() const; };", cxxMethodDecl(isConst())));
   EXPECT_TRUE(
-    notMatches("struct A { void foo(); };", cxxMethodDecl(isConst())));
+      notMatches("struct A { void foo(); };", cxxMethodDecl(isConst())));
 }
 
 TEST(Matcher, MatchesOverridingMethod) {
   EXPECT_TRUE(matches("class X { virtual int f(); }; "
-                        "class Y : public X { int f(); };",
+                      "class Y : public X { int f(); };",
                       cxxMethodDecl(isOverride(), hasName("::Y::f"))));
   EXPECT_TRUE(notMatches("class X { virtual int f(); }; "
-                           "class Y : public X { int f(); };",
+                         "class Y : public X { int f(); };",
                          cxxMethodDecl(isOverride(), hasName("::X::f"))));
   EXPECT_TRUE(notMatches("class X { int f(); }; "
-                           "class Y : public X { int f(); };",
+                         "class Y : public X { int f(); };",
                          cxxMethodDecl(isOverride())));
   EXPECT_TRUE(notMatches("class X { int f(); int f(int); }; ",
                          cxxMethodDecl(isOverride())));
   EXPECT_TRUE(
-    matches("template  struct Y : Base { void f() override;};",
-            cxxMethodDecl(isOverride(), hasName("::Y::f"))));
+      matches("template  struct Y : Base { void f() override;};",
+              cxxMethodDecl(isOverride(), hasName("::Y::f"))));
 }
 
 TEST(Matcher, ConstructorArgument) {
@@ -1385,44 +1341,38 @@ TEST(Matcher, ConstructorArgument) {
       ast_type_traits::TK_AsIs,
       cxxConstructExpr(hasArgument(0, declRefExpr(to(varDecl(hasName("y")))))));
 
+  EXPECT_TRUE(matches(
+      "class X { public: X(int); }; void x() { int y; X x(y); }", Constructor));
   EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { int y; X x(y); }",
-            Constructor));
-  EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { int y; X x = X(y); }",
-            Constructor));
-  EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { int y; X x = y; }",
-            Constructor));
+      matches("class X { public: X(int); }; void x() { int y; X x = X(y); }",
+              Constructor));
   EXPECT_TRUE(
-    notMatches("class X { public: X(int); }; void x() { int z; X x(z); }",
-               Constructor));
+      matches("class X { public: X(int); }; void x() { int y; X x = y; }",
+              Constructor));
+  EXPECT_TRUE(notMatches(
+      "class X { public: X(int); }; void x() { int z; X x(z); }", Constructor));
 
   StatementMatcher WrongIndex =
       traverse(ast_type_traits::TK_AsIs,
                cxxConstructExpr(
                    hasArgument(42, declRefExpr(to(varDecl(hasName("y")))))));
-  EXPECT_TRUE(
-    notMatches("class X { public: X(int); }; void x() { int y; X x(y); }",
-               WrongIndex));
+  EXPECT_TRUE(notMatches(
+      "class X { public: X(int); }; void x() { int y; X x(y); }", WrongIndex));
 }
 
 TEST(Matcher, ConstructorArgumentCount) {
   auto Constructor1Arg =
       traverse(ast_type_traits::TK_AsIs, cxxConstructExpr(argumentCountIs(1)));
 
+  EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x(0); }",
+                      Constructor1Arg));
+  EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x = X(0); }",
+                      Constructor1Arg));
+  EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x = 0; }",
+                      Constructor1Arg));
   EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { X x(0); }",
-            Constructor1Arg));
-  EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { X x = X(0); }",
-            Constructor1Arg));
-  EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { X x = 0; }",
-            Constructor1Arg));
-  EXPECT_TRUE(
-    notMatches("class X { public: X(int, int); }; void x() { X x(0, 0); }",
-               Constructor1Arg));
+      notMatches("class X { public: X(int, int); }; void x() { X x(0, 0); }",
+                 Constructor1Arg));
 }
 
 TEST(Matcher, ConstructorListInitialization) {
@@ -1430,19 +1380,16 @@ TEST(Matcher, ConstructorListInitialization) {
       traverse(ast_type_traits::TK_AsIs,
                varDecl(has(cxxConstructExpr(isListInitialization()))));
 
-  EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { X x{0}; }",
-            ConstructorListInit));
-  EXPECT_FALSE(
-    matches("class X { public: X(int); }; void x() { X x(0); }",
-            ConstructorListInit));
+  EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x{0}; }",
+                      ConstructorListInit));
+  EXPECT_FALSE(matches("class X { public: X(int); }; void x() { X x(0); }",
+                       ConstructorListInit));
 }
 
 TEST(ConstructorDeclaration, IsImplicit) {
   // This one doesn't match because the constructor is not added by the
   // compiler (it is not needed).
-  EXPECT_TRUE(notMatches("class Foo { };",
-                         cxxConstructorDecl(isImplicit())));
+  EXPECT_TRUE(notMatches("class Foo { };", cxxConstructorDecl(isImplicit())));
   // The compiler added the implicit default constructor.
   EXPECT_TRUE(matches("class Foo { }; Foo* f = new Foo();",
                       cxxConstructorDecl(isImplicit())));
@@ -1456,8 +1403,8 @@ TEST(ConstructorDeclaration, IsImplicit) {
 TEST(ConstructorDeclaration, IsExplicit) {
   EXPECT_TRUE(matches("struct S { explicit S(int); };",
                       cxxConstructorDecl(isExplicit())));
-  EXPECT_TRUE(notMatches("struct S { S(int); };",
-                         cxxConstructorDecl(isExplicit())));
+  EXPECT_TRUE(
+      notMatches("struct S { S(int); };", cxxConstructorDecl(isExplicit())));
   EXPECT_TRUE(notMatches("template struct S { explicit(b) S(int);};",
                          cxxConstructorDecl(isExplicit()), langCxx20OrLater()));
   EXPECT_TRUE(matches("struct S { explicit(true) S(int);};",
@@ -1488,9 +1435,9 @@ TEST(DeductionGuideDeclaration, IsExplicit) {
 }
 
 TEST(ConstructorDeclaration, Kinds) {
-  EXPECT_TRUE(matches(
-      "struct S { S(); };",
-      cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit()))));
+  EXPECT_TRUE(
+      matches("struct S { S(); };", cxxConstructorDecl(isDefaultConstructor(),
+                                                       unless(isImplicit()))));
   EXPECT_TRUE(notMatches(
       "struct S { S(); };",
       cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
@@ -1501,9 +1448,9 @@ TEST(ConstructorDeclaration, Kinds) {
   EXPECT_TRUE(notMatches(
       "struct S { S(const S&); };",
       cxxConstructorDecl(isDefaultConstructor(), unless(isImplicit()))));
-  EXPECT_TRUE(matches(
-      "struct S { S(const S&); };",
-      cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
+  EXPECT_TRUE(
+      matches("struct S { S(const S&); };",
+              cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
   EXPECT_TRUE(notMatches(
       "struct S { S(const S&); };",
       cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
@@ -1514,9 +1461,9 @@ TEST(ConstructorDeclaration, Kinds) {
   EXPECT_TRUE(notMatches(
       "struct S { S(S&&); };",
       cxxConstructorDecl(isCopyConstructor(), unless(isImplicit()))));
-  EXPECT_TRUE(matches(
-      "struct S { S(S&&); };",
-      cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
+  EXPECT_TRUE(
+      matches("struct S { S(S&&); };",
+              cxxConstructorDecl(isMoveConstructor(), unless(isImplicit()))));
 }
 
 TEST(ConstructorDeclaration, IsUserProvided) {
@@ -1527,7 +1474,7 @@ TEST(ConstructorDeclaration, IsUserProvided) {
   EXPECT_TRUE(notMatches("struct S { S() = delete; };",
                          cxxConstructorDecl(isUserProvided())));
   EXPECT_TRUE(
-    matches("struct S { S(); };", cxxConstructorDecl(isUserProvided())));
+      matches("struct S { S(); };", cxxConstructorDecl(isUserProvided())));
   EXPECT_TRUE(matches("struct S { S(); }; S::S(){}",
                       cxxConstructorDecl(isUserProvided())));
 }
@@ -1538,11 +1485,11 @@ TEST(ConstructorDeclaration, IsDelegatingConstructor) {
   EXPECT_TRUE(notMatches("struct S { S(){} S(int X) : X(X) {} int X; };",
                          cxxConstructorDecl(isDelegatingConstructor())));
   EXPECT_TRUE(matches(
-    "struct S { S() : S(0) {} S(int X) : X(X) {} int X; };",
-    cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(0))));
+      "struct S { S() : S(0) {} S(int X) : X(X) {} int X; };",
+      cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(0))));
   EXPECT_TRUE(matches(
-    "struct S { S(); S(int X); int X; }; S::S(int X) : S() {}",
-    cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(1))));
+      "struct S { S(); S(int X); int X; }; S::S(int X) : S() {}",
+      cxxConstructorDecl(isDelegatingConstructor(), parameterCountIs(1))));
 }
 
 TEST(StringLiteral, HasSize) {
@@ -1584,38 +1531,28 @@ TEST(Matcher, HasNameSupportsNamespaces) {
 }
 
 TEST(Matcher, HasNameSupportsOuterClasses) {
-  EXPECT_TRUE(
-    matches("class A { class B { class C; }; };",
-            recordDecl(hasName("A::B::C"))));
-  EXPECT_TRUE(
-    matches("class A { class B { class C; }; };",
-            recordDecl(hasName("::A::B::C"))));
-  EXPECT_TRUE(
-    matches("class A { class B { class C; }; };",
-            recordDecl(hasName("B::C"))));
-  EXPECT_TRUE(
-    matches("class A { class B { class C; }; };",
-            recordDecl(hasName("C"))));
-  EXPECT_TRUE(
-    notMatches("class A { class B { class C; }; };",
-               recordDecl(hasName("c::B::C"))));
-  EXPECT_TRUE(
-    notMatches("class A { class B { class C; }; };",
-               recordDecl(hasName("A::c::C"))));
-  EXPECT_TRUE(
-    notMatches("class A { class B { class C; }; };",
-               recordDecl(hasName("A::B::A"))));
-  EXPECT_TRUE(
-    notMatches("class A { class B { class C; }; };",
-               recordDecl(hasName("::C"))));
-  EXPECT_TRUE(
-    notMatches("class A { class B { class C; }; };",
-               recordDecl(hasName("::B::C"))));
+  EXPECT_TRUE(matches("class A { class B { class C; }; };",
+                      recordDecl(hasName("A::B::C"))));
+  EXPECT_TRUE(matches("class A { class B { class C; }; };",
+                      recordDecl(hasName("::A::B::C"))));
+  EXPECT_TRUE(matches("class A { class B { class C; }; };",
+                      recordDecl(hasName("B::C"))));
+  EXPECT_TRUE(
+      matches("class A { class B { class C; }; };", recordDecl(hasName("C"))));
+  EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
+                         recordDecl(hasName("c::B::C"))));
+  EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
+                         recordDecl(hasName("A::c::C"))));
+  EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
+                         recordDecl(hasName("A::B::A"))));
+  EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
+                         recordDecl(hasName("::C"))));
+  EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
+                         recordDecl(hasName("::B::C"))));
   EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
                          recordDecl(hasName("z::A::B::C"))));
-  EXPECT_TRUE(
-    notMatches("class A { class B { class C; }; };",
-               recordDecl(hasName("A+B::C"))));
+  EXPECT_TRUE(notMatches("class A { class B { class C; }; };",
+                         recordDecl(hasName("A+B::C"))));
 }
 
 TEST(Matcher, HasNameSupportsInlinedNamespaces) {
@@ -1629,10 +1566,10 @@ TEST(Matcher, HasNameSupportsInlinedNamespaces) {
 TEST(Matcher, HasNameSupportsAnonymousNamespaces) {
   StringRef code = "namespace a { namespace { class C; } }";
   EXPECT_TRUE(
-    matches(code, recordDecl(hasName("a::(anonymous namespace)::C"))));
+      matches(code, recordDecl(hasName("a::(anonymous namespace)::C"))));
   EXPECT_TRUE(matches(code, recordDecl(hasName("a::C"))));
   EXPECT_TRUE(
-    matches(code, recordDecl(hasName("::a::(anonymous namespace)::C"))));
+      matches(code, recordDecl(hasName("::a::(anonymous namespace)::C"))));
   EXPECT_TRUE(matches(code, recordDecl(hasName("::a::C"))));
 }
 
@@ -1689,7 +1626,7 @@ TEST(Matcher, HasAnyName) {
 
   EXPECT_TRUE(notMatches(Code, recordDecl(hasAnyName("::C", "::b::C"))));
   EXPECT_TRUE(
-    matches(Code, recordDecl(hasAnyName("::C", "::b::C", "::a::b::C"))));
+      matches(Code, recordDecl(hasAnyName("::C", "::b::C", "::a::b::C"))));
 
   std::vector Names = {"::C", "::b::C", "::a::b::C"};
   EXPECT_TRUE(matches(Code, recordDecl(hasAnyName(Names))));
@@ -1697,27 +1634,27 @@ TEST(Matcher, HasAnyName) {
 
 TEST(Matcher, IsDefinition) {
   DeclarationMatcher DefinitionOfClassA =
-    recordDecl(hasName("A"), isDefinition());
+      recordDecl(hasName("A"), isDefinition());
   EXPECT_TRUE(matches("class A {};", DefinitionOfClassA));
   EXPECT_TRUE(notMatches("class A;", DefinitionOfClassA));
 
   DeclarationMatcher DefinitionOfVariableA =
-    varDecl(hasName("a"), isDefinition());
+      varDecl(hasName("a"), isDefinition());
   EXPECT_TRUE(matches("int a;", DefinitionOfVariableA));
   EXPECT_TRUE(notMatches("extern int a;", DefinitionOfVariableA));
 
   DeclarationMatcher DefinitionOfMethodA =
-    cxxMethodDecl(hasName("a"), isDefinition());
+      cxxMethodDecl(hasName("a"), isDefinition());
   EXPECT_TRUE(matches("class A { void a() {} };", DefinitionOfMethodA));
   EXPECT_TRUE(notMatches("class A { void a(); };", DefinitionOfMethodA));
 
   DeclarationMatcher DefinitionOfObjCMethodA =
-    objcMethodDecl(hasName("a"), isDefinition());
+      objcMethodDecl(hasName("a"), isDefinition());
   EXPECT_TRUE(matchesObjC("@interface A @end "
                           "@implementation A; -(void)a {} @end",
                           DefinitionOfObjCMethodA));
-  EXPECT_TRUE(notMatchesObjC("@interface A; - (void)a; @end",
-                             DefinitionOfObjCMethodA));
+  EXPECT_TRUE(
+      notMatchesObjC("@interface A; - (void)a; @end", DefinitionOfObjCMethodA));
 }
 
 TEST(Matcher, HandlesNullQualTypes) {
@@ -1728,7 +1665,7 @@ TEST(Matcher, HandlesNullQualTypes) {
   // We don't really care whether this matcher succeeds; we're testing that
   // it completes without crashing.
   EXPECT_TRUE(matches(
-    "struct A { };"
+      "struct A { };"
       "template "
       "void f(T t) {"
       "  T local_t(t /* this becomes a null QualType in the AST */);"
@@ -1736,13 +1673,10 @@ TEST(Matcher, HandlesNullQualTypes) {
       "void g() {"
       "  f(0);"
       "}",
-    expr(hasType(TypeMatcher(
-      anyOf(
-        TypeMatcher(hasDeclaration(anything())),
-        pointsTo(AnyType),
-        references(AnyType)
-        // Other QualType matchers should go here.
-      ))))));
+      expr(hasType(TypeMatcher(anyOf(TypeMatcher(hasDeclaration(anything())),
+                                     pointsTo(AnyType), references(AnyType)
+                                     // Other QualType matchers should go here.
+                                     ))))));
 }
 
 TEST(ObjCIvarRefExprMatcher, IvarExpr) {
@@ -1750,10 +1684,10 @@ TEST(ObjCIvarRefExprMatcher, IvarExpr) {
       "@interface A @end "
       "@implementation A { A *x; } - (void) func { x = 0; } @end";
   EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr()));
-  EXPECT_TRUE(matchesObjC(ObjCString, objcIvarRefExpr(
-        hasDeclaration(namedDecl(hasName("x"))))));
-  EXPECT_FALSE(matchesObjC(ObjCString, objcIvarRefExpr(
-        hasDeclaration(namedDecl(hasName("y"))))));
+  EXPECT_TRUE(matchesObjC(
+      ObjCString, objcIvarRefExpr(hasDeclaration(namedDecl(hasName("x"))))));
+  EXPECT_FALSE(matchesObjC(
+      ObjCString, objcIvarRefExpr(hasDeclaration(namedDecl(hasName("y"))))));
 }
 
 TEST(BlockExprMatcher, BlockExpr) {
@@ -1761,24 +1695,19 @@ TEST(BlockExprMatcher, BlockExpr) {
 }
 
 TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) {
-  EXPECT_TRUE(matches("void f() { }",
-                      compoundStmt(statementCountIs(0))));
-  EXPECT_TRUE(notMatches("void f() {}",
-                         compoundStmt(statementCountIs(1))));
+  EXPECT_TRUE(matches("void f() { }", compoundStmt(statementCountIs(0))));
+  EXPECT_TRUE(notMatches("void f() {}", compoundStmt(statementCountIs(1))));
 }
 
 TEST(StatementCountIs, AppearsToMatchOnlyOneCount) {
-  EXPECT_TRUE(matches("void f() { 1; }",
-                      compoundStmt(statementCountIs(1))));
-  EXPECT_TRUE(notMatches("void f() { 1; }",
-                         compoundStmt(statementCountIs(0))));
-  EXPECT_TRUE(notMatches("void f() { 1; }",
-                         compoundStmt(statementCountIs(2))));
+  EXPECT_TRUE(matches("void f() { 1; }", compoundStmt(statementCountIs(1))));
+  EXPECT_TRUE(notMatches("void f() { 1; }", compoundStmt(statementCountIs(0))));
+  EXPECT_TRUE(notMatches("void f() { 1; }", compoundStmt(statementCountIs(2))));
 }
 
 TEST(StatementCountIs, WorksWithMultipleStatements) {
-  EXPECT_TRUE(matches("void f() { 1; 2; 3; }",
-                      compoundStmt(statementCountIs(3))));
+  EXPECT_TRUE(
+      matches("void f() { 1; 2; 3; }", compoundStmt(statementCountIs(3))));
 }
 
 TEST(StatementCountIs, WorksWithNestedCompoundStatements) {
@@ -1806,19 +1735,19 @@ TEST(Member, DoesNotMatchTheBaseExpression) {
 
 TEST(Member, MatchesInMemberFunctionCall) {
   EXPECT_TRUE(matches("void f() {"
-                        "  struct { void first() {}; } s;"
-                        "  s.first();"
-                        "};",
+                      "  struct { void first() {}; } s;"
+                      "  s.first();"
+                      "};",
                       memberExpr(member(hasName("first")))));
 }
 
 TEST(Member, MatchesMember) {
-  EXPECT_TRUE(matches(
-    "struct A { int i; }; void f() { A a; a.i = 2; }",
-    memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
-  EXPECT_TRUE(notMatches(
-    "struct A { float f; }; void f() { A a; a.f = 2.0f; }",
-    memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
+  EXPECT_TRUE(
+      matches("struct A { int i; }; void f() { A a; a.i = 2; }",
+              memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
+  EXPECT_TRUE(
+      notMatches("struct A { float f; }; void f() { A a; a.f = 2.0f; }",
+                 memberExpr(hasDeclaration(fieldDecl(hasType(isInteger()))))));
 }
 
 TEST(Member, BitFields) {
@@ -1841,26 +1770,26 @@ TEST(Member, InClassInitializer) {
 }
 
 TEST(Member, UnderstandsAccess) {
-  EXPECT_TRUE(matches(
-    "struct A { int i; };", fieldDecl(isPublic(), hasName("i"))));
-  EXPECT_TRUE(notMatches(
-    "struct A { int i; };", fieldDecl(isProtected(), hasName("i"))));
-  EXPECT_TRUE(notMatches(
-    "struct A { int i; };", fieldDecl(isPrivate(), hasName("i"))));
+  EXPECT_TRUE(
+      matches("struct A { int i; };", fieldDecl(isPublic(), hasName("i"))));
+  EXPECT_TRUE(notMatches("struct A { int i; };",
+                         fieldDecl(isProtected(), hasName("i"))));
+  EXPECT_TRUE(
+      notMatches("struct A { int i; };", fieldDecl(isPrivate(), hasName("i"))));
 
-  EXPECT_TRUE(notMatches(
-    "class A { int i; };", fieldDecl(isPublic(), hasName("i"))));
-  EXPECT_TRUE(notMatches(
-    "class A { int i; };", fieldDecl(isProtected(), hasName("i"))));
-  EXPECT_TRUE(matches(
-    "class A { int i; };", fieldDecl(isPrivate(), hasName("i"))));
+  EXPECT_TRUE(
+      notMatches("class A { int i; };", fieldDecl(isPublic(), hasName("i"))));
+  EXPECT_TRUE(notMatches("class A { int i; };",
+                         fieldDecl(isProtected(), hasName("i"))));
+  EXPECT_TRUE(
+      matches("class A { int i; };", fieldDecl(isPrivate(), hasName("i"))));
 
-  EXPECT_TRUE(notMatches(
-    "class A { protected: int i; };", fieldDecl(isPublic(), hasName("i"))));
+  EXPECT_TRUE(notMatches("class A { protected: int i; };",
+                         fieldDecl(isPublic(), hasName("i"))));
   EXPECT_TRUE(matches("class A { protected: int i; };",
                       fieldDecl(isProtected(), hasName("i"))));
-  EXPECT_TRUE(notMatches(
-    "class A { protected: int i; };", fieldDecl(isPrivate(), hasName("i"))));
+  EXPECT_TRUE(notMatches("class A { protected: int i; };",
+                         fieldDecl(isPrivate(), hasName("i"))));
 
   // Non-member decls have the AccessSpecifier AS_none and thus aren't matched.
   EXPECT_TRUE(notMatches("int i;", varDecl(isPublic(), hasName("i"))));
@@ -1883,35 +1812,35 @@ TEST(hasDynamicExceptionSpec, MatchesDynamicExceptionSpecifications) {
   EXPECT_TRUE(
       matches("void l() throw(...);", functionDecl(hasDynamicExceptionSpec())));
 
-  EXPECT_TRUE(notMatches("void f();", functionProtoType(hasDynamicExceptionSpec())));
+  EXPECT_TRUE(
+      notMatches("void f();", functionProtoType(hasDynamicExceptionSpec())));
   EXPECT_TRUE(notMatches("void g() noexcept;",
                          functionProtoType(hasDynamicExceptionSpec())));
   EXPECT_TRUE(notMatches("void h() noexcept(true);",
                          functionProtoType(hasDynamicExceptionSpec())));
   EXPECT_TRUE(notMatches("void i() noexcept(false);",
                          functionProtoType(hasDynamicExceptionSpec())));
-  EXPECT_TRUE(
-      matches("void j() throw();", functionProtoType(hasDynamicExceptionSpec())));
-  EXPECT_TRUE(
-      matches("void k() throw(int);", functionProtoType(hasDynamicExceptionSpec())));
-  EXPECT_TRUE(
-      matches("void l() throw(...);", functionProtoType(hasDynamicExceptionSpec())));
+  EXPECT_TRUE(matches("void j() throw();",
+                      functionProtoType(hasDynamicExceptionSpec())));
+  EXPECT_TRUE(matches("void k() throw(int);",
+                      functionProtoType(hasDynamicExceptionSpec())));
+  EXPECT_TRUE(matches("void l() throw(...);",
+                      functionProtoType(hasDynamicExceptionSpec())));
 }
 
 TEST(HasObjectExpression, DoesNotMatchMember) {
   EXPECT_TRUE(notMatches(
-    "class X {}; struct Z { X m; }; void f(Z z) { z.m; }",
-    memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
+      "class X {}; struct Z { X m; }; void f(Z z) { z.m; }",
+      memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
 }
 
 TEST(HasObjectExpression, MatchesBaseOfVariable) {
   EXPECT_TRUE(matches(
-    "struct X { int m; }; void f(X x) { x.m; }",
-    memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
-  EXPECT_TRUE(matches(
-    "struct X { int m; }; void f(X* x) { x->m; }",
-    memberExpr(hasObjectExpression(
-      hasType(pointsTo(recordDecl(hasName("X"))))))));
+      "struct X { int m; }; void f(X x) { x.m; }",
+      memberExpr(hasObjectExpression(hasType(recordDecl(hasName("X")))))));
+  EXPECT_TRUE(matches("struct X { int m; }; void f(X* x) { x->m; }",
+                      memberExpr(hasObjectExpression(
+                          hasType(pointsTo(recordDecl(hasName("X"))))))));
   EXPECT_TRUE(matches("template  struct X { void f() { T t; t.m; } };",
                       cxxDependentScopeMemberExpr(hasObjectExpression(
                           declRefExpr(to(namedDecl(hasName("t"))))))));
@@ -1936,14 +1865,12 @@ TEST(HasObjectExpression, MatchesBaseOfMemberFunc) {
 
 TEST(HasObjectExpression,
      MatchesObjectExpressionOfImplicitlyFormedMemberExpression) {
-  EXPECT_TRUE(matches(
-    "class X {}; struct S { X m; void f() { this->m; } };",
-    memberExpr(hasObjectExpression(
-      hasType(pointsTo(recordDecl(hasName("S"))))))));
-  EXPECT_TRUE(matches(
-    "class X {}; struct S { X m; void f() { m; } };",
-    memberExpr(hasObjectExpression(
-      hasType(pointsTo(recordDecl(hasName("S"))))))));
+  EXPECT_TRUE(matches("class X {}; struct S { X m; void f() { this->m; } };",
+                      memberExpr(hasObjectExpression(
+                          hasType(pointsTo(recordDecl(hasName("S"))))))));
+  EXPECT_TRUE(matches("class X {}; struct S { X m; void f() { m; } };",
+                      memberExpr(hasObjectExpression(
+                          hasType(pointsTo(recordDecl(hasName("S"))))))));
 }
 
 TEST(Field, DoesNotMatchNonFieldMembers) {
@@ -1958,17 +1885,17 @@ TEST(Field, MatchesField) {
 }
 
 TEST(IsVolatileQualified, QualifiersMatch) {
-  EXPECT_TRUE(matches("volatile int i = 42;",
-                      varDecl(hasType(isVolatileQualified()))));
-  EXPECT_TRUE(notMatches("volatile int *i;",
-                         varDecl(hasType(isVolatileQualified()))));
+  EXPECT_TRUE(
+      matches("volatile int i = 42;", varDecl(hasType(isVolatileQualified()))));
+  EXPECT_TRUE(
+      notMatches("volatile int *i;", varDecl(hasType(isVolatileQualified()))));
   EXPECT_TRUE(matches("typedef volatile int v_int; v_int i = 42;",
                       varDecl(hasType(isVolatileQualified()))));
 }
 
 TEST(IsConstQualified, MatchesConstInt) {
-  EXPECT_TRUE(matches("const int i = 42;",
-                      varDecl(hasType(isConstQualified()))));
+  EXPECT_TRUE(
+      matches("const int i = 42;", varDecl(hasType(isConstQualified()))));
 }
 
 TEST(IsConstQualified, MatchesConstPointer) {
@@ -1986,43 +1913,41 @@ TEST(IsConstQualified, MatchesThroughTypedef) {
 TEST(IsConstQualified, DoesNotMatchInappropriately) {
   EXPECT_TRUE(notMatches("typedef int nonconst_int; nonconst_int i = 42;",
                          varDecl(hasType(isConstQualified()))));
-  EXPECT_TRUE(notMatches("int const* p;",
-                         varDecl(hasType(isConstQualified()))));
+  EXPECT_TRUE(
+      notMatches("int const* p;", varDecl(hasType(isConstQualified()))));
 }
 
 TEST(DeclCount, DeclCountIsCorrect) {
-  EXPECT_TRUE(matches("void f() {int i,j;}",
-                      declStmt(declCountIs(2))));
-  EXPECT_TRUE(notMatches("void f() {int i,j; int k;}",
-                         declStmt(declCountIs(3))));
-  EXPECT_TRUE(notMatches("void f() {int i,j, k, l;}",
-                         declStmt(declCountIs(3))));
+  EXPECT_TRUE(matches("void f() {int i,j;}", declStmt(declCountIs(2))));
+  EXPECT_TRUE(
+      notMatches("void f() {int i,j; int k;}", declStmt(declCountIs(3))));
+  EXPECT_TRUE(
+      notMatches("void f() {int i,j, k, l;}", declStmt(declCountIs(3))));
 }
 
-
 TEST(EachOf, TriggersForEachMatch) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "class A { int a; int b; };",
-    recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
-                      has(fieldDecl(hasName("b")).bind("v")))),
-    std::make_unique>("v", 2)));
+      "class A { int a; int b; };",
+      recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+                        has(fieldDecl(hasName("b")).bind("v")))),
+      std::make_unique>("v", 2)));
 }
 
 TEST(EachOf, BehavesLikeAnyOfUnlessBothMatch) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "class A { int a; int c; };",
-    recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
-                      has(fieldDecl(hasName("b")).bind("v")))),
-    std::make_unique>("v", 1)));
+      "class A { int a; int c; };",
+      recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+                        has(fieldDecl(hasName("b")).bind("v")))),
+      std::make_unique>("v", 1)));
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "class A { int c; int b; };",
-    recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
-                      has(fieldDecl(hasName("b")).bind("v")))),
-    std::make_unique>("v", 1)));
-  EXPECT_TRUE(notMatches(
-    "class A { int c; int d; };",
-    recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
-                      has(fieldDecl(hasName("b")).bind("v"))))));
+      "class A { int c; int b; };",
+      recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+                        has(fieldDecl(hasName("b")).bind("v")))),
+      std::make_unique>("v", 1)));
+  EXPECT_TRUE(
+      notMatches("class A { int c; int d; };",
+                 recordDecl(eachOf(has(fieldDecl(hasName("a")).bind("v")),
+                                   has(fieldDecl(hasName("b")).bind("v"))))));
 }
 
 TEST(Optionally, SubmatchersDoNotMatch) {
@@ -2056,29 +1981,30 @@ TEST(IsTemplateInstantiation, MatchesImplicitClassTemplateInstantiation) {
   // Make sure that we can both match the class by name (::X) and by the type
   // the template was instantiated with (via a field).
 
-  EXPECT_TRUE(matches(
-    "template  class X {}; class A {}; X x;",
-    cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
+  EXPECT_TRUE(
+      matches("template  class X {}; class A {}; X x;",
+              cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
 
   EXPECT_TRUE(matches(
-    "template  class X { T t; }; class A {}; X x;",
-    cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
-      fieldDecl(hasType(recordDecl(hasName("A"))))))));
+      "template  class X { T t; }; class A {}; X x;",
+      cxxRecordDecl(
+          isTemplateInstantiation(),
+          hasDescendant(fieldDecl(hasType(recordDecl(hasName("A"))))))));
 }
 
 TEST(IsTemplateInstantiation, MatchesImplicitFunctionTemplateInstantiation) {
   EXPECT_TRUE(matches(
-    "template  void f(T t) {} class A {}; void g() { f(A()); }",
-    functionDecl(hasParameter(0, hasType(recordDecl(hasName("A")))),
-                 isTemplateInstantiation())));
+      "template  void f(T t) {} class A {}; void g() { f(A()); }",
+      functionDecl(hasParameter(0, hasType(recordDecl(hasName("A")))),
+                   isTemplateInstantiation())));
 }
 
 TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
-  EXPECT_TRUE(matches(
-    "template  class X { T t; }; class A {};"
-      "template class X;",
-    cxxRecordDecl(isTemplateInstantiation(), hasDescendant(
-      fieldDecl(hasType(recordDecl(hasName("A"))))))));
+  EXPECT_TRUE(matches("template  class X { T t; }; class A {};"
+                      "template class X;",
+                      cxxRecordDecl(isTemplateInstantiation(),
+                                    hasDescendant(fieldDecl(
+                                        hasType(recordDecl(hasName("A"))))))));
 
   // Make sure that we match the instantiation instead of the template
   // definition by checking whether the member function is present.
@@ -2091,21 +2017,21 @@ TEST(IsTemplateInstantiation, MatchesExplicitClassTemplateInstantiation) {
 
 TEST(IsTemplateInstantiation,
      MatchesInstantiationOfPartiallySpecializedClassTemplate) {
-  EXPECT_TRUE(matches(
-    "template  class X {};"
-      "template  class X {}; class A {}; X x;",
-    cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
+  EXPECT_TRUE(
+      matches("template  class X {};"
+              "template  class X {}; class A {}; X x;",
+              cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
 }
 
 TEST(IsTemplateInstantiation,
      MatchesInstantiationOfClassTemplateNestedInNonTemplate) {
-  EXPECT_TRUE(matches(
-    "class A {};"
-      "class X {"
-      "  template  class Y { U u; };"
-      "  Y y;"
-      "};",
-    cxxRecordDecl(hasName("::X::Y"), isTemplateInstantiation())));
+  EXPECT_TRUE(
+      matches("class A {};"
+              "class X {"
+              "  template  class Y { U u; };"
+              "  Y y;"
+              "};",
+              cxxRecordDecl(hasName("::X::Y"), isTemplateInstantiation())));
 }
 
 TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
@@ -2113,31 +2039,30 @@ TEST(IsTemplateInstantiation, DoesNotMatchInstantiationsInsideOfInstantiation) {
   // normal use case as long as the uppermost instantiation always is marked
   // as template instantiation, but it might be confusing as a predicate.
   EXPECT_TRUE(matches(
-    "class A {};"
+      "class A {};"
       "template  class X {"
       "  template  class Y { U u; };"
       "  Y y;"
       "}; X x;",
-    cxxRecordDecl(hasName("::X::Y"), unless(isTemplateInstantiation()))));
+      cxxRecordDecl(hasName("::X::Y"), unless(isTemplateInstantiation()))));
 }
 
 TEST(IsTemplateInstantiation, DoesNotMatchExplicitClassTemplateSpecialization) {
-  EXPECT_TRUE(notMatches(
-    "template  class X {}; class A {};"
-      "template <> class X {}; X x;",
-    cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
+  EXPECT_TRUE(
+      notMatches("template  class X {}; class A {};"
+                 "template <> class X {}; X x;",
+                 cxxRecordDecl(hasName("::X"), isTemplateInstantiation())));
 }
 
 TEST(IsTemplateInstantiation, DoesNotMatchNonTemplate) {
-  EXPECT_TRUE(notMatches(
-    "class A {}; class Y { A a; };",
-    cxxRecordDecl(isTemplateInstantiation())));
+  EXPECT_TRUE(notMatches("class A {}; class Y { A a; };",
+                         cxxRecordDecl(isTemplateInstantiation())));
 }
 
 TEST(IsInstantiated, MatchesInstantiation) {
   EXPECT_TRUE(
-    matches("template class A { T i; }; class Y { A a; };",
-            cxxRecordDecl(isInstantiated())));
+      matches("template class A { T i; }; class Y { A a; };",
+              cxxRecordDecl(isInstantiated())));
 }
 
 TEST(IsInstantiated, NotMatchesDefinition) {
@@ -2147,7 +2072,7 @@ TEST(IsInstantiated, NotMatchesDefinition) {
 
 TEST(IsInTemplateInstantiation, MatchesInstantiationStmt) {
   EXPECT_TRUE(matches("template struct A { A() { T i; } };"
-                        "class Y { A a; }; Y y;",
+                      "class Y { A a; }; Y y;",
                       declStmt(isInTemplateInstantiation())));
 }
 
@@ -2158,8 +2083,8 @@ TEST(IsInTemplateInstantiation, NotMatchesDefinitionStmt) {
 
 TEST(IsInstantiated, MatchesFunctionInstantiation) {
   EXPECT_TRUE(
-    matches("template void A(T t) { T i; } void x() { A(0); }",
-            functionDecl(isInstantiated())));
+      matches("template void A(T t) { T i; } void x() { A(0); }",
+              functionDecl(isInstantiated())));
 }
 
 TEST(IsInstantiated, NotMatchesFunctionDefinition) {
@@ -2169,8 +2094,8 @@ TEST(IsInstantiated, NotMatchesFunctionDefinition) {
 
 TEST(IsInTemplateInstantiation, MatchesFunctionInstantiationStmt) {
   EXPECT_TRUE(
-    matches("template void A(T t) { T i; } void x() { A(0); }",
-            declStmt(isInTemplateInstantiation())));
+      matches("template void A(T t) { T i; } void x() { A(0); }",
+              declStmt(isInTemplateInstantiation())));
 }
 
 TEST(IsInTemplateInstantiation, NotMatchesFunctionDefinitionStmt) {
@@ -2183,11 +2108,11 @@ TEST(IsInTemplateInstantiation, Sharing) {
   // FIXME: Node sharing is an implementation detail, exposing it is ugly
   // and makes the matcher behave in non-obvious ways.
   EXPECT_TRUE(notMatches(
-    "int j; template void A(T t) { j += 42; } void x() { A(0); }",
-    Matcher));
+      "int j; template void A(T t) { j += 42; } void x() { A(0); }",
+      Matcher));
   EXPECT_TRUE(matches(
-    "int j; template void A(T t) { j += t; } void x() { A(0); }",
-    Matcher));
+      "int j; template void A(T t) { j += t; } void x() { A(0); }",
+      Matcher));
 }
 
 TEST(IsInstantiationDependent, MatchesNonValueTypeDependent) {
@@ -2232,48 +2157,41 @@ TEST(IsValueDependent, MatchesInstantiationDependent) {
       expr(isValueDependent())));
 }
 
-TEST(IsExplicitTemplateSpecialization,
-     DoesNotMatchPrimaryTemplate) {
-  EXPECT_TRUE(notMatches(
-    "template  class X {};",
-    cxxRecordDecl(isExplicitTemplateSpecialization())));
-  EXPECT_TRUE(notMatches(
-    "template  void f(T t);",
-    functionDecl(isExplicitTemplateSpecialization())));
+TEST(IsExplicitTemplateSpecialization, DoesNotMatchPrimaryTemplate) {
+  EXPECT_TRUE(notMatches("template  class X {};",
+                         cxxRecordDecl(isExplicitTemplateSpecialization())));
+  EXPECT_TRUE(notMatches("template  void f(T t);",
+                         functionDecl(isExplicitTemplateSpecialization())));
 }
 
 TEST(IsExplicitTemplateSpecialization,
      DoesNotMatchExplicitTemplateInstantiations) {
-  EXPECT_TRUE(notMatches(
-    "template  class X {};"
-      "template class X; extern template class X;",
-    cxxRecordDecl(isExplicitTemplateSpecialization())));
-  EXPECT_TRUE(notMatches(
-    "template  void f(T t) {}"
-      "template void f(int t); extern template void f(long t);",
-    functionDecl(isExplicitTemplateSpecialization())));
+  EXPECT_TRUE(
+      notMatches("template  class X {};"
+                 "template class X; extern template class X;",
+                 cxxRecordDecl(isExplicitTemplateSpecialization())));
+  EXPECT_TRUE(
+      notMatches("template  void f(T t) {}"
+                 "template void f(int t); extern template void f(long t);",
+                 functionDecl(isExplicitTemplateSpecialization())));
 }
 
 TEST(IsExplicitTemplateSpecialization,
      DoesNotMatchImplicitTemplateInstantiations) {
-  EXPECT_TRUE(notMatches(
-    "template  class X {}; X x;",
-    cxxRecordDecl(isExplicitTemplateSpecialization())));
-  EXPECT_TRUE(notMatches(
-    "template  void f(T t); void g() { f(10); }",
-    functionDecl(isExplicitTemplateSpecialization())));
+  EXPECT_TRUE(notMatches("template  class X {}; X x;",
+                         cxxRecordDecl(isExplicitTemplateSpecialization())));
+  EXPECT_TRUE(
+      notMatches("template  void f(T t); void g() { f(10); }",
+                 functionDecl(isExplicitTemplateSpecialization())));
 }
 
-TEST(IsExplicitTemplateSpecialization,
-     MatchesExplicitTemplateSpecializations) {
-  EXPECT_TRUE(matches(
-    "template  class X {};"
-      "template<> class X {};",
-    cxxRecordDecl(isExplicitTemplateSpecialization())));
-  EXPECT_TRUE(matches(
-    "template  void f(T t) {}"
-      "template<> void f(int t) {}",
-    functionDecl(isExplicitTemplateSpecialization())));
+TEST(IsExplicitTemplateSpecialization, MatchesExplicitTemplateSpecializations) {
+  EXPECT_TRUE(matches("template  class X {};"
+                      "template<> class X {};",
+                      cxxRecordDecl(isExplicitTemplateSpecialization())));
+  EXPECT_TRUE(matches("template  void f(T t) {}"
+                      "template<> void f(int t) {}",
+                      functionDecl(isExplicitTemplateSpecialization())));
 }
 
 TEST(TypeMatching, MatchesNoReturn) {
@@ -2314,8 +2232,8 @@ TEST(TypeMatching, MatchesNoReturn) {
 
   EXPECT_TRUE(
       matches("struct S { [[noreturn]] S(); };", functionDecl(isNoReturn())));
-  EXPECT_TRUE(matches("struct S { [[noreturn]] S() {} };",
-                      functionDecl(isNoReturn())));
+  EXPECT_TRUE(
+      matches("struct S { [[noreturn]] S() {} };", functionDecl(isNoReturn())));
 
   // ---
 
@@ -2344,14 +2262,12 @@ TEST(TypeMatching, MatchesNoReturn) {
   // ---
 
   EXPECT_TRUE(matchesC("__attribute__((noreturn)) void func();",
-                      functionDecl(isNoReturn())));
+                       functionDecl(isNoReturn())));
   EXPECT_TRUE(matchesC("__attribute__((noreturn)) void func() {}",
-                      functionDecl(isNoReturn())));
+                       functionDecl(isNoReturn())));
 
-  EXPECT_TRUE(matchesC("_Noreturn void func();",
-                      functionDecl(isNoReturn())));
-  EXPECT_TRUE(matchesC("_Noreturn void func() {}",
-                      functionDecl(isNoReturn())));
+  EXPECT_TRUE(matchesC("_Noreturn void func();", functionDecl(isNoReturn())));
+  EXPECT_TRUE(matchesC("_Noreturn void func() {}", functionDecl(isNoReturn())));
 }
 
 TEST(TypeMatching, MatchesBool) {
@@ -2383,45 +2299,42 @@ TEST(TypeMatching, MatchesArrayTypes) {
   EXPECT_TRUE(notMatches("struct A {}; A a[7];",
                          arrayType(hasElementType(builtinType()))));
 
+  EXPECT_TRUE(matches("int const a[] = { 2, 3 };",
+                      qualType(arrayType(hasElementType(builtinType())))));
   EXPECT_TRUE(matches(
-    "int const a[] = { 2, 3 };",
-    qualType(arrayType(hasElementType(builtinType())))));
-  EXPECT_TRUE(matches(
-    "int const a[] = { 2, 3 };",
-    qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
-  EXPECT_TRUE(matches(
-    "typedef const int T; T x[] = { 1, 2 };",
-    qualType(isConstQualified(), arrayType())));
+      "int const a[] = { 2, 3 };",
+      qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
+  EXPECT_TRUE(matches("typedef const int T; T x[] = { 1, 2 };",
+                      qualType(isConstQualified(), arrayType())));
 
   EXPECT_TRUE(notMatches(
-    "int a[] = { 2, 3 };",
-    qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
-  EXPECT_TRUE(notMatches(
-    "int a[] = { 2, 3 };",
-    qualType(arrayType(hasElementType(isConstQualified(), builtinType())))));
+      "int a[] = { 2, 3 };",
+      qualType(isConstQualified(), arrayType(hasElementType(builtinType())))));
   EXPECT_TRUE(notMatches(
-    "int const a[] = { 2, 3 };",
-    qualType(arrayType(hasElementType(builtinType())),
-             unless(isConstQualified()))));
+      "int a[] = { 2, 3 };",
+      qualType(arrayType(hasElementType(isConstQualified(), builtinType())))));
+  EXPECT_TRUE(notMatches("int const a[] = { 2, 3 };",
+                         qualType(arrayType(hasElementType(builtinType())),
+                                  unless(isConstQualified()))));
 
-  EXPECT_TRUE(matches("int a[2];",
-                      constantArrayType(hasElementType(builtinType()))));
+  EXPECT_TRUE(
+      matches("int a[2];", constantArrayType(hasElementType(builtinType()))));
   EXPECT_TRUE(matches("const int a = 0;", qualType(isInteger())));
 }
 
 TEST(TypeMatching, DecayedType) {
-  EXPECT_TRUE(matches("void f(int i[]);", valueDecl(hasType(decayedType(hasDecayedType(pointerType()))))));
+  EXPECT_TRUE(
+      matches("void f(int i[]);",
+              valueDecl(hasType(decayedType(hasDecayedType(pointerType()))))));
   EXPECT_TRUE(notMatches("int i[7];", decayedType()));
 }
 
 TEST(TypeMatching, MatchesComplexTypes) {
   EXPECT_TRUE(matches("_Complex float f;", complexType()));
-  EXPECT_TRUE(matches(
-    "_Complex float f;",
-    complexType(hasElementType(builtinType()))));
-  EXPECT_TRUE(notMatches(
-    "_Complex float f;",
-    complexType(hasElementType(isInteger()))));
+  EXPECT_TRUE(
+      matches("_Complex float f;", complexType(hasElementType(builtinType()))));
+  EXPECT_TRUE(notMatches("_Complex float f;",
+                         complexType(hasElementType(isInteger()))));
 }
 
 TEST(NS, Anonymous) {
@@ -2482,38 +2395,38 @@ TEST(DeclarationMatcher, InStdNamespace) {
 
 TEST(EqualsBoundNodeMatcher, QualType) {
   EXPECT_TRUE(matches(
-    "int i = 1;", varDecl(hasType(qualType().bind("type")),
-                          hasInitializer(ignoringParenImpCasts(
-                            hasType(qualType(equalsBoundNode("type"))))))));
+      "int i = 1;", varDecl(hasType(qualType().bind("type")),
+                            hasInitializer(ignoringParenImpCasts(
+                                hasType(qualType(equalsBoundNode("type"))))))));
   EXPECT_TRUE(notMatches("int i = 1.f;",
                          varDecl(hasType(qualType().bind("type")),
                                  hasInitializer(ignoringParenImpCasts(hasType(
-                                   qualType(equalsBoundNode("type"))))))));
+                                     qualType(equalsBoundNode("type"))))))));
 }
 
 TEST(EqualsBoundNodeMatcher, NonMatchingTypes) {
   EXPECT_TRUE(notMatches(
-    "int i = 1;", varDecl(namedDecl(hasName("i")).bind("name"),
-                          hasInitializer(ignoringParenImpCasts(
-                            hasType(qualType(equalsBoundNode("type"))))))));
+      "int i = 1;", varDecl(namedDecl(hasName("i")).bind("name"),
+                            hasInitializer(ignoringParenImpCasts(
+                                hasType(qualType(equalsBoundNode("type"))))))));
 }
 
 TEST(EqualsBoundNodeMatcher, Stmt) {
   EXPECT_TRUE(
-    matches("void f() { if(true) {} }",
-            stmt(allOf(ifStmt().bind("if"),
-                       hasParent(stmt(has(stmt(equalsBoundNode("if")))))))));
+      matches("void f() { if(true) {} }",
+              stmt(allOf(ifStmt().bind("if"),
+                         hasParent(stmt(has(stmt(equalsBoundNode("if")))))))));
 
   EXPECT_TRUE(notMatches(
-    "void f() { if(true) { if (true) {} } }",
-    stmt(allOf(ifStmt().bind("if"), has(stmt(equalsBoundNode("if")))))));
+      "void f() { if(true) { if (true) {} } }",
+      stmt(allOf(ifStmt().bind("if"), has(stmt(equalsBoundNode("if")))))));
 }
 
 TEST(EqualsBoundNodeMatcher, Decl) {
   EXPECT_TRUE(matches(
-    "class X { class Y {}; };",
-    decl(allOf(recordDecl(hasName("::X::Y")).bind("record"),
-               hasParent(decl(has(decl(equalsBoundNode("record")))))))));
+      "class X { class Y {}; };",
+      decl(allOf(recordDecl(hasName("::X::Y")).bind("record"),
+                 hasParent(decl(has(decl(equalsBoundNode("record")))))))));
 
   EXPECT_TRUE(notMatches("class X { class Y {}; };",
                          decl(allOf(recordDecl(hasName("::X")).bind("record"),
@@ -2522,21 +2435,21 @@ TEST(EqualsBoundNodeMatcher, Decl) {
 
 TEST(EqualsBoundNodeMatcher, Type) {
   EXPECT_TRUE(matches(
-    "class X { int a; int b; };",
-    recordDecl(
-      has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
-      has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))));
+      "class X { int a; int b; };",
+      recordDecl(
+          has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
+          has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))));
 
   EXPECT_TRUE(notMatches(
-    "class X { int a; double b; };",
-    recordDecl(
-      has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
-      has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))));
+      "class X { int a; double b; };",
+      recordDecl(
+          has(fieldDecl(hasName("a"), hasType(type().bind("t")))),
+          has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t"))))))));
 }
 
 TEST(EqualsBoundNodeMatcher, UsingForEachDescendant) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "int f() {"
+      "int f() {"
       "  if (1) {"
       "    int i = 9;"
       "  }"
@@ -2546,63 +2459,65 @@ TEST(EqualsBoundNodeMatcher, UsingForEachDescendant) {
       "  }"
       "  return 0;"
       "}",
-    // Look for variable declarations within functions whose type is the same
-    // as the function return type.
-    functionDecl(returns(qualType().bind("type")),
-                 forEachDescendant(varDecl(hasType(
-                   qualType(equalsBoundNode("type")))).bind("decl"))),
-    // Only i and j should match, not k.
-    std::make_unique>("decl", 2)));
+      // Look for variable declarations within functions whose type is the same
+      // as the function return type.
+      functionDecl(
+          returns(qualType().bind("type")),
+          forEachDescendant(varDecl(hasType(qualType(equalsBoundNode("type"))))
+                                .bind("decl"))),
+      // Only i and j should match, not k.
+      std::make_unique>("decl", 2)));
 }
 
 TEST(EqualsBoundNodeMatcher, FiltersMatchedCombinations) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "void f() {"
+      "void f() {"
       "  int x;"
       "  double d;"
       "  x = d + x - d + x;"
       "}",
-    functionDecl(
-      hasName("f"), forEachDescendant(varDecl().bind("d")),
-      forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d")))))),
-    std::make_unique>("d", 5)));
+      functionDecl(
+          hasName("f"), forEachDescendant(varDecl().bind("d")),
+          forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d")))))),
+      std::make_unique>("d", 5)));
 }
 
 TEST(EqualsBoundNodeMatcher, UnlessDescendantsOfAncestorsMatch) {
   EXPECT_TRUE(matchAndVerifyResultTrue(
-    "struct StringRef { int size() const; const char* data() const; };"
+      "struct StringRef { int size() const; const char* data() const; };"
       "void f(StringRef v) {"
       "  v.data();"
       "}",
-    cxxMemberCallExpr(
-      callee(cxxMethodDecl(hasName("data"))),
-      on(declRefExpr(to(
-        varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
-      unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
-        callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
-        on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
-      .bind("data"),
-    std::make_unique>("data", 1)));
+      cxxMemberCallExpr(
+          callee(cxxMethodDecl(hasName("data"))),
+          on(declRefExpr(to(
+              varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
+          unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
+              callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
+              on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
+          .bind("data"),
+      std::make_unique>("data", 1)));
 
   EXPECT_FALSE(matches(
-    "struct StringRef { int size() const; const char* data() const; };"
+      "struct StringRef { int size() const; const char* data() const; };"
       "void f(StringRef v) {"
       "  v.data();"
       "  v.size();"
       "}",
-    cxxMemberCallExpr(
-      callee(cxxMethodDecl(hasName("data"))),
-      on(declRefExpr(to(
-        varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
-      unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
-        callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
-        on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
-      .bind("data")));
+      cxxMemberCallExpr(
+          callee(cxxMethodDecl(hasName("data"))),
+          on(declRefExpr(to(
+              varDecl(hasType(recordDecl(hasName("StringRef")))).bind("var")))),
+          unless(hasAncestor(stmt(hasDescendant(cxxMemberCallExpr(
+              callee(cxxMethodDecl(anyOf(hasName("size"), hasName("length")))),
+              on(declRefExpr(to(varDecl(equalsBoundNode("var")))))))))))
+          .bind("data")));
 }
 
 TEST(NullPointerConstants, Basic) {
   EXPECT_TRUE(matches("#define NULL ((void *)0)\n"
-                        "void *v1 = NULL;", expr(nullPointerConstant())));
+                      "void *v1 = NULL;",
+                      expr(nullPointerConstant())));
   EXPECT_TRUE(matches("void *v2 = nullptr;", expr(nullPointerConstant())));
   EXPECT_TRUE(matches("void *v3 = __null;", expr(nullPointerConstant())));
   EXPECT_TRUE(matches("char *cp = (char *)0;", expr(nullPointerConstant())));
@@ -2635,10 +2550,10 @@ TEST(HasExternalFormalLinkage, Basic) {
 }
 
 TEST(HasDefaultArgument, Basic) {
-  EXPECT_TRUE(matches("void x(int val = 0) {}",
-                      parmVarDecl(hasDefaultArgument())));
-  EXPECT_TRUE(notMatches("void x(int val) {}",
-                      parmVarDecl(hasDefaultArgument())));
+  EXPECT_TRUE(
+      matches("void x(int val = 0) {}", parmVarDecl(hasDefaultArgument())));
+  EXPECT_TRUE(
+      notMatches("void x(int val) {}", parmVarDecl(hasDefaultArgument())));
 }
 
 TEST(IsAtPosition, Basic) {
@@ -2691,24 +2606,18 @@ TEST(HasArraySize, Basic) {
 }
 
 TEST(HasDefinition, MatchesStructDefinition) {
-  EXPECT_TRUE(matches("struct x {};",
-                      cxxRecordDecl(hasDefinition())));
-  EXPECT_TRUE(notMatches("struct x;",
-                      cxxRecordDecl(hasDefinition())));
+  EXPECT_TRUE(matches("struct x {};", cxxRecordDecl(hasDefinition())));
+  EXPECT_TRUE(notMatches("struct x;", cxxRecordDecl(hasDefinition())));
 }
 
 TEST(HasDefinition, MatchesClassDefinition) {
-  EXPECT_TRUE(matches("class x {};",
-                      cxxRecordDecl(hasDefinition())));
-  EXPECT_TRUE(notMatches("class x;",
-                      cxxRecordDecl(hasDefinition())));
+  EXPECT_TRUE(matches("class x {};", cxxRecordDecl(hasDefinition())));
+  EXPECT_TRUE(notMatches("class x;", cxxRecordDecl(hasDefinition())));
 }
 
 TEST(HasDefinition, MatchesUnionDefinition) {
-  EXPECT_TRUE(matches("union x {};",
-                      cxxRecordDecl(hasDefinition())));
-  EXPECT_TRUE(notMatches("union x;",
-                      cxxRecordDecl(hasDefinition())));
+  EXPECT_TRUE(matches("union x {};", cxxRecordDecl(hasDefinition())));
+  EXPECT_TRUE(notMatches("union x;", cxxRecordDecl(hasDefinition())));
 }
 
 TEST(IsScopedEnum, MatchesScopedEnum) {
@@ -2727,19 +2636,19 @@ TEST(HasTrailingReturn, MatchesTrailingReturn) {
   EXPECT_TRUE(matches("auto Y() -> int { return 0; }",
                       functionDecl(hasTrailingReturn())));
   EXPECT_TRUE(matches("auto X() -> int;", functionDecl(hasTrailingReturn())));
-  EXPECT_TRUE(notMatches("int X() { return 0; }",
-                      functionDecl(hasTrailingReturn())));
+  EXPECT_TRUE(
+      notMatches("int X() { return 0; }", functionDecl(hasTrailingReturn())));
   EXPECT_TRUE(notMatches("int X();", functionDecl(hasTrailingReturn())));
   EXPECT_TRUE(notMatchesC("void X();", functionDecl(hasTrailingReturn())));
 }
 
 TEST(HasTrailingReturn, MatchesLambdaTrailingReturn) {
   EXPECT_TRUE(matches(
-          "auto lambda2 = [](double x, double y) -> double {return x + y;};",
-          functionDecl(hasTrailingReturn())));
-  EXPECT_TRUE(notMatches(
-          "auto lambda2 = [](double x, double y) {return x + y;};",
-          functionDecl(hasTrailingReturn())));
+      "auto lambda2 = [](double x, double y) -> double {return x + y;};",
+      functionDecl(hasTrailingReturn())));
+  EXPECT_TRUE(
+      notMatches("auto lambda2 = [](double x, double y) {return x + y;};",
+                 functionDecl(hasTrailingReturn())));
 }
 
 TEST(IsAssignmentOperator, Basic) {
@@ -2772,23 +2681,15 @@ TEST(IsComparisonOperator, Basic) {
 }
 
 TEST(HasInit, Basic) {
-  EXPECT_TRUE(
-    matches("int x{0};",
-            initListExpr(hasInit(0, expr()))));
-  EXPECT_FALSE(
-    matches("int x{0};",
-            initListExpr(hasInit(1, expr()))));
-  EXPECT_FALSE(
-    matches("int x;",
-            initListExpr(hasInit(0, expr()))));
+  EXPECT_TRUE(matches("int x{0};", initListExpr(hasInit(0, expr()))));
+  EXPECT_FALSE(matches("int x{0};", initListExpr(hasInit(1, expr()))));
+  EXPECT_FALSE(matches("int x;", initListExpr(hasInit(0, expr()))));
 }
 
 TEST(Matcher, isMain) {
-  EXPECT_TRUE(
-    matches("int main() {}", functionDecl(isMain())));
+  EXPECT_TRUE(matches("int main() {}", functionDecl(isMain())));
 
-  EXPECT_TRUE(
-    notMatches("int main2() {}", functionDecl(isMain())));
+  EXPECT_TRUE(notMatches("int main2() {}", functionDecl(isMain())));
 }
 
 TEST(OMPExecutableDirective, isStandaloneDirective) {
@@ -2867,11 +2768,18 @@ void x() {
   EXPECT_TRUE(matchesWithOpenMP(Source3, Matcher));
 
   StringRef Source4 = R"(
+void x() {
+#pragma omp parallel default(firstprivate)
+;
+})";
+  EXPECT_TRUE(matchesWithOpenMP51(Source4, Matcher));
+
+  StringRef Source5 = R"(
 void x(int x) {
 #pragma omp parallel num_threads(x)
 ;
 })";
-  EXPECT_TRUE(matchesWithOpenMP(Source4, Matcher));
+  EXPECT_TRUE(matchesWithOpenMP(Source5, Matcher));
 }
 
 TEST(OMPDefaultClause, isNoneKind) {
@@ -2907,10 +2815,17 @@ void x() {
 
   StringRef Source4 = R"(
 void x(int x) {
+#pragma omp parallel default(firstprivate)
+;
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP51(Source4, Matcher));
+
+  const std::string Source5 = R"(
+void x(int x) {
 #pragma omp parallel num_threads(x)
 ;
 })";
-  EXPECT_TRUE(notMatchesWithOpenMP(Source4, Matcher));
+  EXPECT_TRUE(notMatchesWithOpenMP(Source5, Matcher));
 }
 
 TEST(OMPDefaultClause, isSharedKind) {
@@ -2946,10 +2861,63 @@ void x() {
 
   StringRef Source4 = R"(
 void x(int x) {
+#pragma omp parallel default(firstprivate)
+;
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP51(Source4, Matcher));
+
+  const std::string Source5 = R"(
+void x(int x) {
 #pragma omp parallel num_threads(x)
 ;
 })";
-  EXPECT_TRUE(notMatchesWithOpenMP(Source4, Matcher));
+  EXPECT_TRUE(notMatchesWithOpenMP(Source5, Matcher));
+}
+
+TEST(OMPDefaultClause, isFirstPrivateKind) {
+  auto Matcher = ompExecutableDirective(
+      hasAnyClause(ompDefaultClause(isFirstPrivateKind())));
+
+  const std::string Source0 = R"(
+void x() {
+;
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP(Source0, Matcher));
+
+  const std::string Source1 = R"(
+void x() {
+#pragma omp parallel
+;
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP(Source1, Matcher));
+
+  const std::string Source2 = R"(
+void x() {
+#pragma omp parallel default(shared)
+;
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP(Source2, Matcher));
+
+  const std::string Source3 = R"(
+void x() {
+#pragma omp parallel default(none)
+;
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP(Source3, Matcher));
+
+  const std::string Source4 = R"(
+void x(int x) {
+#pragma omp parallel default(firstprivate)
+;
+})";
+  EXPECT_TRUE(matchesWithOpenMP51(Source4, Matcher));
+
+  const std::string Source5 = R"(
+void x(int x) {
+#pragma omp parallel num_threads(x)
+;
+})";
+  EXPECT_TRUE(notMatchesWithOpenMP(Source5, Matcher));
 }
 
 TEST(OMPExecutableDirective, isAllowedToContainClauseKind) {
@@ -2984,24 +2952,31 @@ void x() {
   EXPECT_TRUE(matchesWithOpenMP(Source3, Matcher));
 
   StringRef Source4 = R"(
+void x() {
+#pragma omp parallel default(firstprivate)
+;
+})";
+  EXPECT_TRUE(matchesWithOpenMP51(Source4, Matcher));
+
+  StringRef Source5 = R"(
 void x(int x) {
 #pragma omp parallel num_threads(x)
 ;
 })";
-  EXPECT_TRUE(matchesWithOpenMP(Source4, Matcher));
+  EXPECT_TRUE(matchesWithOpenMP(Source5, Matcher));
 
-  StringRef Source5 = R"(
+  StringRef Source6 = R"(
 void x() {
 #pragma omp taskyield
 })";
-  EXPECT_TRUE(notMatchesWithOpenMP(Source5, Matcher));
+  EXPECT_TRUE(notMatchesWithOpenMP(Source6, Matcher));
 
-  StringRef Source6 = R"(
+  StringRef Source7 = R"(
 void x() {
 #pragma omp task
 ;
 })";
-  EXPECT_TRUE(matchesWithOpenMP(Source6, Matcher));
+  EXPECT_TRUE(matchesWithOpenMP(Source7, Matcher));
 }
 
 TEST(HasAnyBase, DirectBase) {
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
index 59e0f74b3910b..895c8ae48adc1 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -118,13 +118,13 @@ TEST_P(ASTMatchersTest, TranslationUnitDecl) {
                    "int MyVar2;\n"
                    "}  // namespace NameSpace\n";
   EXPECT_TRUE(matches(
-    Code, varDecl(hasName("MyVar1"), hasDeclContext(translationUnitDecl()))));
+      Code, varDecl(hasName("MyVar1"), hasDeclContext(translationUnitDecl()))));
   EXPECT_FALSE(matches(
-    Code, varDecl(hasName("MyVar2"), hasDeclContext(translationUnitDecl()))));
+      Code, varDecl(hasName("MyVar2"), hasDeclContext(translationUnitDecl()))));
   EXPECT_TRUE(matches(
-    Code,
-    varDecl(hasName("MyVar2"),
-            hasDeclContext(decl(hasDeclContext(translationUnitDecl()))))));
+      Code,
+      varDecl(hasName("MyVar2"),
+              hasDeclContext(decl(hasDeclContext(translationUnitDecl()))))));
 }
 
 TEST_P(ASTMatchersTest, LinkageSpecDecl) {
@@ -158,10 +158,10 @@ TEST_P(ASTMatchersTest,
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(notMatches("template class X { };"
-                           "template<> class X { int a; };",
-                         classTemplateDecl(hasName("X"),
-                                           hasDescendant(fieldDecl(hasName("a"))))));
+  EXPECT_TRUE(notMatches(
+      "template class X { };"
+      "template<> class X { int a; };",
+      classTemplateDecl(hasName("X"), hasDescendant(fieldDecl(hasName("a"))))));
 }
 
 TEST_P(ASTMatchersTest,
@@ -169,18 +169,17 @@ TEST_P(ASTMatchersTest,
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(notMatches("template class X { };"
-                           "template class X { int a; };",
-                         classTemplateDecl(hasName("X"),
-                                           hasDescendant(fieldDecl(hasName("a"))))));
+  EXPECT_TRUE(notMatches(
+      "template class X { };"
+      "template class X { int a; };",
+      classTemplateDecl(hasName("X"), hasDescendant(fieldDecl(hasName("a"))))));
 }
 
 TEST(ASTMatchersTestCUDA, CUDAKernelCallExpr) {
   EXPECT_TRUE(matchesWithCuda("__global__ void f() { }"
-                                "void g() { f<<<1, 2>>>(); }",
+                              "void g() { f<<<1, 2>>>(); }",
                               cudaKernelCallExpr()));
-  EXPECT_TRUE(notMatchesWithCuda("void f() {}",
-                                 cudaKernelCallExpr()));
+  EXPECT_TRUE(notMatchesWithCuda("void f() {}", cudaKernelCallExpr()));
 }
 
 TEST(ASTMatchersTestCUDA, HasAttrCUDA) {
@@ -316,56 +315,50 @@ TEST_P(ASTMatchersTest, CallExpr_CXX) {
   // FIXME: Do we want to overload Call() to directly take
   // Matcher, too?
   StatementMatcher MethodX =
-    callExpr(hasDeclaration(cxxMethodDecl(hasName("x"))));
+      callExpr(hasDeclaration(cxxMethodDecl(hasName("x"))));
 
   EXPECT_TRUE(matches("class Y { void x() { x(); } };", MethodX));
   EXPECT_TRUE(notMatches("class Y { void x() {} };", MethodX));
 
   StatementMatcher MethodOnY =
-    cxxMemberCallExpr(on(hasType(recordDecl(hasName("Y")))));
+      cxxMemberCallExpr(on(hasType(recordDecl(hasName("Y")))));
 
-  EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
-            MethodOnY));
-  EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
-            MethodOnY));
-  EXPECT_TRUE(
-    notMatches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
-               MethodOnY));
-  EXPECT_TRUE(
-    notMatches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
-               MethodOnY));
-  EXPECT_TRUE(
-    notMatches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
-               MethodOnY));
+  EXPECT_TRUE(matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
+                      MethodOnY));
+  EXPECT_TRUE(matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
+                      MethodOnY));
+  EXPECT_TRUE(notMatches(
+      "class Y { public: void x(); }; void z(Y *&y) { y->x(); }", MethodOnY));
+  EXPECT_TRUE(notMatches(
+      "class Y { public: void x(); }; void z(Y y[]) { y->x(); }", MethodOnY));
+  EXPECT_TRUE(notMatches(
+      "class Y { public: void x(); }; void z() { Y *y; y->x(); }", MethodOnY));
 
   StatementMatcher MethodOnYPointer =
-    cxxMemberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));
+      cxxMemberCallExpr(on(hasType(pointsTo(recordDecl(hasName("Y"))))));
 
   EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
-            MethodOnYPointer));
+      matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
+              MethodOnYPointer));
   EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
-            MethodOnYPointer));
+      matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
+              MethodOnYPointer));
   EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
-            MethodOnYPointer));
+      matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
+              MethodOnYPointer));
   EXPECT_TRUE(
-    notMatches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
-               MethodOnYPointer));
+      notMatches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
+                 MethodOnYPointer));
   EXPECT_TRUE(
-    notMatches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
-               MethodOnYPointer));
+      notMatches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
+                 MethodOnYPointer));
 }
 
 TEST_P(ASTMatchersTest, LambdaExpr) {
   if (!GetParam().isCXX11OrLater()) {
     return;
   }
-  EXPECT_TRUE(matches("auto f = [] (int i) { return i; };",
-                      lambdaExpr()));
+  EXPECT_TRUE(matches("auto f = [] (int i) { return i; };", lambdaExpr()));
 }
 
 TEST_P(ASTMatchersTest, CXXForRangeStmt) {
@@ -378,7 +371,7 @@ TEST_P(ASTMatchersTest, CXXForRangeStmt_CXX11) {
     return;
   }
   EXPECT_TRUE(matches("int as[] = { 1, 2, 3 };"
-                        "void f() { for (auto &a : as); }",
+                      "void f() { for (auto &a : as); }",
                       cxxForRangeStmt()));
 }
 
@@ -387,15 +380,13 @@ TEST_P(ASTMatchersTest, SubstNonTypeTemplateParmExpr) {
     return;
   }
   EXPECT_FALSE(matches("template\n"
-                         "struct A {  static const int n = 0; };\n"
-                         "struct B : public A<42> {};",
-                         traverse(TK_AsIs,
-                       substNonTypeTemplateParmExpr())));
+                       "struct A {  static const int n = 0; };\n"
+                       "struct B : public A<42> {};",
+                       traverse(TK_AsIs, substNonTypeTemplateParmExpr())));
   EXPECT_TRUE(matches("template\n"
-                        "struct A {  static const int n = N; };\n"
-                        "struct B : public A<42> {};",
-                         traverse(TK_AsIs,
-                      substNonTypeTemplateParmExpr())));
+                      "struct A {  static const int n = N; };\n"
+                      "struct B : public A<42> {};",
+                      traverse(TK_AsIs, substNonTypeTemplateParmExpr())));
 }
 
 TEST_P(ASTMatchersTest, NonTypeTemplateParmDecl) {
@@ -405,7 +396,7 @@ TEST_P(ASTMatchersTest, NonTypeTemplateParmDecl) {
   EXPECT_TRUE(matches("template  void f();",
                       nonTypeTemplateParmDecl(hasName("N"))));
   EXPECT_TRUE(
-    notMatches("template  void f();", nonTypeTemplateParmDecl()));
+      notMatches("template  void f();", nonTypeTemplateParmDecl()));
 }
 
 TEST_P(ASTMatchersTest, TemplateTypeParmDecl) {
@@ -414,8 +405,7 @@ TEST_P(ASTMatchersTest, TemplateTypeParmDecl) {
   }
   EXPECT_TRUE(matches("template  void f();",
                       templateTypeParmDecl(hasName("T"))));
-  EXPECT_TRUE(
-    notMatches("template  void f();", templateTypeParmDecl()));
+  EXPECT_TRUE(notMatches("template  void f();", templateTypeParmDecl()));
 }
 
 TEST_P(ASTMatchersTest, UserDefinedLiteral) {
@@ -423,9 +413,9 @@ TEST_P(ASTMatchersTest, UserDefinedLiteral) {
     return;
   }
   EXPECT_TRUE(matches("constexpr char operator \"\" _inc (const char i) {"
-                        "  return i + 1;"
-                        "}"
-                        "char c = 'a'_inc;",
+                      "  return i + 1;"
+                      "}"
+                      "char c = 'a'_inc;",
                       userDefinedLiteral()));
 }
 
@@ -434,9 +424,7 @@ TEST_P(ASTMatchersTest, FlowControl) {
   EXPECT_TRUE(matches("void f() { while(1) { continue; } }", continueStmt()));
   EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}", gotoStmt()));
   EXPECT_TRUE(matches("void f() { goto FOO; FOO: ;}",
-                      labelStmt(
-                        hasDeclaration(
-                          labelDecl(hasName("FOO"))))));
+                      labelStmt(hasDeclaration(labelDecl(hasName("FOO"))))));
   EXPECT_TRUE(matches("void f() { FOO: ; void *ptr = &&FOO; goto *ptr; }",
                       addrLabelExpr()));
   EXPECT_TRUE(matches("void f() { return; }", returnStmt()));
@@ -450,8 +438,9 @@ TEST_P(ASTMatchersTest, CXXOperatorCallExpr) {
   StatementMatcher OpCall = cxxOperatorCallExpr();
   // Unary operator
   EXPECT_TRUE(matches("class Y { }; "
-                        "bool operator!(Y x) { return false; }; "
-                        "Y y; bool c = !y;", OpCall));
+                      "bool operator!(Y x) { return false; }; "
+                      "Y y; bool c = !y;",
+                      OpCall));
   // No match -- special operators like "new", "delete"
   // FIXME: operator new takes size_t, for which we need stddef.h, for which
   // we need to figure out include paths in the test.
@@ -460,12 +449,13 @@ TEST_P(ASTMatchersTest, CXXOperatorCallExpr) {
   //             "void *operator new(size_t size) { return 0; } "
   //             "Y *y = new Y;", OpCall));
   EXPECT_TRUE(notMatches("class Y { }; "
-                           "void operator delete(void *p) { } "
-                           "void a() {Y *y = new Y; delete y;}", OpCall));
+                         "void operator delete(void *p) { } "
+                         "void a() {Y *y = new Y; delete y;}",
+                         OpCall));
   // Binary operator
   EXPECT_TRUE(matches("class Y { }; "
-                        "bool operator&&(Y x, Y y) { return true; }; "
-                        "Y a; Y b; bool c = a && b;",
+                      "bool operator&&(Y x, Y y) { return true; }; "
+                      "Y a; Y b; bool c = a && b;",
                       OpCall));
   // No match -- normal operator, not an overloaded one.
   EXPECT_TRUE(notMatches("bool x = true, y = true; bool t = x && y;", OpCall));
@@ -481,30 +471,25 @@ TEST_P(ASTMatchersTest, ThisPointerType) {
       traverse(ast_type_traits::TK_AsIs,
                cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y")))));
 
-  EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
-            MethodOnY));
-  EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
-            MethodOnY));
-  EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z(Y *&y) { y->x(); }",
-            MethodOnY));
-  EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z(Y y[]) { y->x(); }",
-            MethodOnY));
-  EXPECT_TRUE(
-    matches("class Y { public: void x(); }; void z() { Y *y; y->x(); }",
-            MethodOnY));
-
+  EXPECT_TRUE(matches("class Y { public: void x(); }; void z() { Y y; y.x(); }",
+                      MethodOnY));
+  EXPECT_TRUE(matches("class Y { public: void x(); }; void z(Y &y) { y.x(); }",
+                      MethodOnY));
   EXPECT_TRUE(matches(
-    "class Y {"
-      "  public: virtual void x();"
-      "};"
-      "class X : public Y {"
-      "  public: virtual void x();"
-      "};"
-      "void z() { X *x; x->Y::x(); }", MethodOnY));
+      "class Y { public: void x(); }; void z(Y *&y) { y->x(); }", MethodOnY));
+  EXPECT_TRUE(matches(
+      "class Y { public: void x(); }; void z(Y y[]) { y->x(); }", MethodOnY));
+  EXPECT_TRUE(matches(
+      "class Y { public: void x(); }; void z() { Y *y; y->x(); }", MethodOnY));
+
+  EXPECT_TRUE(matches("class Y {"
+                      "  public: virtual void x();"
+                      "};"
+                      "class X : public Y {"
+                      "  public: virtual void x();"
+                      "};"
+                      "void z() { X *x; x->Y::x(); }",
+                      MethodOnY));
 }
 
 TEST_P(ASTMatchersTest, DeclRefExpr) {
@@ -512,29 +497,27 @@ TEST_P(ASTMatchersTest, DeclRefExpr) {
     // FIXME: Add a test for `declRefExpr()` that does not depend on C++.
     return;
   }
-  StatementMatcher Reference =
-    declRefExpr(to(
-      varDecl(hasInitializer(
-        cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));
+  StatementMatcher Reference = declRefExpr(to(varDecl(hasInitializer(
+      cxxMemberCallExpr(thisPointerType(recordDecl(hasName("Y"))))))));
 
-  EXPECT_TRUE(matches(
-    "class Y {"
-      " public:"
-      "  bool x() const;"
-      "};"
-      "void z(const Y &y) {"
-      "  bool b = y.x();"
-      "  if (b) {}"
-      "}", Reference));
+  EXPECT_TRUE(matches("class Y {"
+                      " public:"
+                      "  bool x() const;"
+                      "};"
+                      "void z(const Y &y) {"
+                      "  bool b = y.x();"
+                      "  if (b) {}"
+                      "}",
+                      Reference));
 
-  EXPECT_TRUE(notMatches(
-    "class Y {"
-      " public:"
-      "  bool x() const;"
-      "};"
-      "void z(const Y &y) {"
-      "  bool b = y.x();"
-      "}", Reference));
+  EXPECT_TRUE(notMatches("class Y {"
+                         " public:"
+                         "  bool x() const;"
+                         "};"
+                         "void z(const Y &y) {"
+                         "  bool b = y.x();"
+                         "}",
+                         Reference));
 }
 
 TEST_P(ASTMatchersTest, CXXMemberCallExpr) {
@@ -542,32 +525,32 @@ TEST_P(ASTMatchersTest, CXXMemberCallExpr) {
     return;
   }
   StatementMatcher CallOnVariableY =
-    cxxMemberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));
-
-  EXPECT_TRUE(matches(
-    "class Y { public: void x() { Y y; y.x(); } };", CallOnVariableY));
-  EXPECT_TRUE(matches(
-    "class Y { public: void x() const { Y y; y.x(); } };", CallOnVariableY));
-  EXPECT_TRUE(matches(
-    "class Y { public: void x(); };"
-      "class X : public Y { void z() { X y; y.x(); } };", CallOnVariableY));
-  EXPECT_TRUE(matches(
-    "class Y { public: void x(); };"
-      "class X : public Y { void z() { X *y; y->x(); } };", CallOnVariableY));
+      cxxMemberCallExpr(on(declRefExpr(to(varDecl(hasName("y"))))));
+
+  EXPECT_TRUE(matches("class Y { public: void x() { Y y; y.x(); } };",
+                      CallOnVariableY));
+  EXPECT_TRUE(matches("class Y { public: void x() const { Y y; y.x(); } };",
+                      CallOnVariableY));
+  EXPECT_TRUE(matches("class Y { public: void x(); };"
+                      "class X : public Y { void z() { X y; y.x(); } };",
+                      CallOnVariableY));
+  EXPECT_TRUE(matches("class Y { public: void x(); };"
+                      "class X : public Y { void z() { X *y; y->x(); } };",
+                      CallOnVariableY));
   EXPECT_TRUE(notMatches(
-    "class Y { public: void x(); };"
+      "class Y { public: void x(); };"
       "class X : public Y { void z() { unsigned long y; ((X*)y)->x(); } };",
-    CallOnVariableY));
+      CallOnVariableY));
 }
 
 TEST_P(ASTMatchersTest, UnaryExprOrTypeTraitExpr) {
-  EXPECT_TRUE(matches("void x() { int a = sizeof(a); }",
-                      unaryExprOrTypeTraitExpr()));
+  EXPECT_TRUE(
+      matches("void x() { int a = sizeof(a); }", unaryExprOrTypeTraitExpr()));
 }
 
 TEST_P(ASTMatchersTest, AlignOfExpr) {
-  EXPECT_TRUE(notMatches("void x() { int a = sizeof(a); }",
-                         alignOfExpr(anything())));
+  EXPECT_TRUE(
+      notMatches("void x() { int a = sizeof(a); }", alignOfExpr(anything())));
   // FIXME: Uncomment once alignof is enabled.
   // EXPECT_TRUE(matches("void x() { int a = alignof(a); }",
   //                     unaryExprOrTypeTraitExpr()));
@@ -603,11 +586,10 @@ TEST_P(ASTMatchersTest, MemberExpr_MatchesVariable) {
     return;
   }
   EXPECT_TRUE(
-    matches("class Y { void x() { this->y; } int y; };", memberExpr()));
-  EXPECT_TRUE(
-    matches("class Y { void x() { y; } int y; };", memberExpr()));
+      matches("class Y { void x() { this->y; } int y; };", memberExpr()));
+  EXPECT_TRUE(matches("class Y { void x() { y; } int y; };", memberExpr()));
   EXPECT_TRUE(
-    matches("class Y { void x() { Y y; y.y; } int y; };", memberExpr()));
+      matches("class Y { void x() { Y y; y.y; } int y; };", memberExpr()));
   EXPECT_TRUE(matches("template "
                       "class X : T { void f() { this->T::v; } };",
                       cxxDependentScopeMemberExpr()));
@@ -623,8 +605,8 @@ TEST_P(ASTMatchersTest, MemberExpr_MatchesStaticVariable) {
   }
   EXPECT_TRUE(matches("class Y { void x() { this->y; } static int y; };",
                       memberExpr()));
-  EXPECT_TRUE(notMatches("class Y { void x() { y; } static int y; };",
-                         memberExpr()));
+  EXPECT_TRUE(
+      notMatches("class Y { void x() { y; } static int y; };", memberExpr()));
   EXPECT_TRUE(notMatches("class Y { void x() { Y::y; } static int y; };",
                          memberExpr()));
 }
@@ -658,21 +640,21 @@ TEST_P(ASTMatchersTest, FunctionDecl_CXX) {
   if (!GetParam().hasDelayedTemplateParsing()) {
     // FIXME: Fix this test to work with delayed template parsing.
     // Dependent contexts, but a non-dependent call.
-    EXPECT_TRUE(matches("void f(); template  void g() { f(); }",
-                        CallFunctionF));
     EXPECT_TRUE(
-      matches("void f(); template  struct S { void g() { f(); } };",
-              CallFunctionF));
+        matches("void f(); template  void g() { f(); }", CallFunctionF));
+    EXPECT_TRUE(
+        matches("void f(); template  struct S { void g() { f(); } };",
+                CallFunctionF));
   }
 
   // Depedent calls don't match.
   EXPECT_TRUE(
-    notMatches("void f(int); template  void g(T t) { f(t); }",
-               CallFunctionF));
+      notMatches("void f(int); template  void g(T t) { f(t); }",
+                 CallFunctionF));
   EXPECT_TRUE(
-    notMatches("void f(int);"
+      notMatches("void f(int);"
                  "template  struct S { void g(T t) { f(t); } };",
-               CallFunctionF));
+                 CallFunctionF));
 
   EXPECT_TRUE(matches("void f(...);", functionDecl(isVariadic())));
   EXPECT_TRUE(matches("void f(...);", functionDecl(parameterCountIs(0))));
@@ -692,9 +674,8 @@ TEST_P(ASTMatchersTest,
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(
-    matches("template  void f(T t) {}",
-            functionTemplateDecl(hasName("f"))));
+  EXPECT_TRUE(matches("template  void f(T t) {}",
+                      functionTemplateDecl(hasName("f"))));
 }
 
 TEST_P(ASTMatchersTest, FunctionTemplate_DoesNotMatchFunctionDeclarations) {
@@ -709,12 +690,11 @@ TEST_P(ASTMatchersTest,
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(
-    notMatches("void g(); template  void f(T t) {}"
-                 "template <> void f(int t) { g(); }",
-               functionTemplateDecl(hasName("f"),
-                                    hasDescendant(declRefExpr(to(
-                                      functionDecl(hasName("g"))))))));
+  EXPECT_TRUE(notMatches(
+      "void g(); template  void f(T t) {}"
+      "template <> void f(int t) { g(); }",
+      functionTemplateDecl(hasName("f"), hasDescendant(declRefExpr(to(
+                                             functionDecl(hasName("g"))))))));
 }
 
 TEST_P(ASTMatchersTest, ClassTemplateSpecializationDecl) {
@@ -722,7 +702,7 @@ TEST_P(ASTMatchersTest, ClassTemplateSpecializationDecl) {
     return;
   }
   EXPECT_TRUE(matches("template struct A {};"
-                        "template<> struct A {};",
+                      "template<> struct A {};",
                       classTemplateSpecializationDecl()));
   EXPECT_TRUE(matches("template struct A {}; A a;",
                       classTemplateSpecializationDecl()));
@@ -756,13 +736,11 @@ TEST_P(ASTMatchersTest, Matcher_ConstructorCall) {
       traverse(ast_type_traits::TK_AsIs, cxxConstructExpr());
 
   EXPECT_TRUE(
-    matches("class X { public: X(); }; void x() { X x; }", Constructor));
-  EXPECT_TRUE(
-    matches("class X { public: X(); }; void x() { X x = X(); }",
-            Constructor));
-  EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { X x = 0; }",
-            Constructor));
+      matches("class X { public: X(); }; void x() { X x; }", Constructor));
+  EXPECT_TRUE(matches("class X { public: X(); }; void x() { X x = X(); }",
+                      Constructor));
+  EXPECT_TRUE(matches("class X { public: X(int); }; void x() { X x = 0; }",
+                      Constructor));
   EXPECT_TRUE(matches("class X {}; void x(int) { X x; }", Constructor));
 }
 
@@ -779,9 +757,9 @@ TEST_P(ASTMatchersTest, Matcher_ThisExpr) {
     return;
   }
   EXPECT_TRUE(
-    matches("struct X { int a; int f () { return a; } };", cxxThisExpr()));
+      matches("struct X { int a; int f () { return a; } };", cxxThisExpr()));
   EXPECT_TRUE(
-    notMatches("struct X { int f () { int a; return a; } };", cxxThisExpr()));
+      notMatches("struct X { int f () { int a; return a; } };", cxxThisExpr()));
 }
 
 TEST_P(ASTMatchersTest, Matcher_BindTemporaryExpression) {
@@ -794,30 +772,27 @@ TEST_P(ASTMatchersTest, Matcher_BindTemporaryExpression) {
 
   StringRef ClassString = "class string { public: string(); ~string(); }; ";
 
-  EXPECT_TRUE(
-    matches(ClassString +
-              "string GetStringByValue();"
-                "void FunctionTakesString(string s);"
-                "void run() { FunctionTakesString(GetStringByValue()); }",
-            TempExpression));
+  EXPECT_TRUE(matches(
+      ClassString + "string GetStringByValue();"
+                    "void FunctionTakesString(string s);"
+                    "void run() { FunctionTakesString(GetStringByValue()); }",
+      TempExpression));
 
-  EXPECT_TRUE(
-    notMatches(ClassString +
-                 "string* GetStringPointer(); "
-                   "void FunctionTakesStringPtr(string* s);"
-                   "void run() {"
-                   "  string* s = GetStringPointer();"
-                   "  FunctionTakesStringPtr(GetStringPointer());"
-                   "  FunctionTakesStringPtr(s);"
-                   "}",
-               TempExpression));
+  EXPECT_TRUE(notMatches(ClassString +
+                             "string* GetStringPointer(); "
+                             "void FunctionTakesStringPtr(string* s);"
+                             "void run() {"
+                             "  string* s = GetStringPointer();"
+                             "  FunctionTakesStringPtr(GetStringPointer());"
+                             "  FunctionTakesStringPtr(s);"
+                             "}",
+                         TempExpression));
 
-  EXPECT_TRUE(
-    notMatches("class no_dtor {};"
-                 "no_dtor GetObjByValue();"
-                 "void ConsumeObj(no_dtor param);"
-                 "void run() { ConsumeObj(GetObjByValue()); }",
-               TempExpression));
+  EXPECT_TRUE(notMatches("class no_dtor {};"
+                         "no_dtor GetObjByValue();"
+                         "void ConsumeObj(no_dtor param);"
+                         "void run() { ConsumeObj(GetObjByValue()); }",
+                         TempExpression));
 }
 
 TEST_P(ASTMatchersTest, MaterializeTemporaryExpr_MatchesTemporaryCXX11CXX14) {
@@ -872,10 +847,9 @@ TEST_P(ASTMatchersTest, Matcher_NewExpression) {
   StatementMatcher New = cxxNewExpr();
 
   EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X; }", New));
+  EXPECT_TRUE(matches("class X { public: X(); }; void x() { new X(); }", New));
   EXPECT_TRUE(
-    matches("class X { public: X(); }; void x() { new X(); }", New));
-  EXPECT_TRUE(
-    matches("class X { public: X(int); }; void x() { new X(0); }", New));
+      matches("class X { public: X(int); }; void x() { new X(0); }", New));
   EXPECT_TRUE(matches("class X {}; void x(int) { new X; }", New));
 }
 
@@ -883,8 +857,8 @@ TEST_P(ASTMatchersTest, Matcher_DeleteExpression) {
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(matches("struct A {}; void f(A* a) { delete a; }",
-                      cxxDeleteExpr()));
+  EXPECT_TRUE(
+      matches("struct A {}; void f(A* a) { delete a; }", cxxDeleteExpr()));
 }
 
 TEST_P(ASTMatchersTest, Matcher_NoexceptExpression) {
@@ -907,7 +881,7 @@ TEST_P(ASTMatchersTest, Matcher_DefaultArgument) {
   StatementMatcher Arg = cxxDefaultArgExpr();
   EXPECT_TRUE(matches("void x(int, int = 0) { int y; x(y); }", Arg));
   EXPECT_TRUE(
-    matches("class X { void x(int, int = 0) { int y; x(y); } };", Arg));
+      matches("class X { void x(int, int = 0) { int y; x(y); } };", Arg));
   EXPECT_TRUE(notMatches("void x(int, int = 0) { int y; x(y, 0); }", Arg));
 }
 
@@ -951,7 +925,7 @@ TEST_P(ASTMatchersTest, IntegerLiteral) {
 
   // Non-matching cases (character literals, float and double)
   EXPECT_TRUE(notMatches("int i = L'a';",
-                         HasIntLiteral));  // this is actually a character
+                         HasIntLiteral)); // this is actually a character
   // literal cast to int
   EXPECT_TRUE(notMatches("int i = 'a';", HasIntLiteral));
   EXPECT_TRUE(notMatches("int i = 1e10;", HasIntLiteral));
@@ -974,13 +948,13 @@ TEST_P(ASTMatchersTest, FloatLiteral) {
   EXPECT_TRUE(matches("double i = 5.0;", floatLiteral(equals(5.0))));
   EXPECT_TRUE(matches("double i = 5.0;", floatLiteral(equals(5.0f))));
   EXPECT_TRUE(
-    matches("double i = 5.0;", floatLiteral(equals(llvm::APFloat(5.0)))));
+      matches("double i = 5.0;", floatLiteral(equals(llvm::APFloat(5.0)))));
 
   EXPECT_TRUE(notMatches("float i = 10;", HasFloatLiteral));
   EXPECT_TRUE(notMatches("double i = 5.0;", floatLiteral(equals(6.0))));
   EXPECT_TRUE(notMatches("double i = 5.0;", floatLiteral(equals(6.0f))));
   EXPECT_TRUE(
-    notMatches("double i = 5.0;", floatLiteral(equals(llvm::APFloat(6.0)))));
+      notMatches("double i = 5.0;", floatLiteral(equals(llvm::APFloat(6.0)))));
 }
 
 TEST_P(ASTMatchersTest, CXXNullPtrLiteralExpr) {
@@ -1051,9 +1025,9 @@ TEST_P(ASTMatchersTest, ParenListExpr) {
     return;
   }
   EXPECT_TRUE(
-    matches("template class foo { void bar() { foo X(*this); } };"
+      matches("template class foo { void bar() { foo X(*this); } };"
               "template class foo;",
-            varDecl(hasInitializer(parenListExpr(has(unaryOperator()))))));
+              varDecl(hasInitializer(parenListExpr(has(unaryOperator()))))));
 }
 
 TEST_P(ASTMatchersTest, StmtExpr) {
@@ -1064,9 +1038,8 @@ TEST_P(ASTMatchersTest, StmtExpr) {
 TEST_P(ASTMatchersTest, PredefinedExpr) {
   // __func__ expands as StringLiteral("foo")
   EXPECT_TRUE(matches("void foo() { __func__; }",
-                      predefinedExpr(
-                        hasType(asString("const char [4]")),
-                        has(stringLiteral()))));
+                      predefinedExpr(hasType(asString("const char [4]")),
+                                     has(stringLiteral()))));
 }
 
 TEST_P(ASTMatchersTest, AsmStatement) {
@@ -1080,7 +1053,7 @@ TEST_P(ASTMatchersTest, HasCondition) {
   }
 
   StatementMatcher Condition =
-    ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
+      ifStmt(hasCondition(cxxBoolLiteral(equals(true))));
 
   EXPECT_TRUE(matches("void x() { if (true) {} }", Condition));
   EXPECT_TRUE(notMatches("void x() { if (false) {} }", Condition));
@@ -1096,24 +1069,24 @@ TEST_P(ASTMatchersTest, ConditionalOperator) {
     return;
   }
 
-  StatementMatcher Conditional = conditionalOperator(
-    hasCondition(cxxBoolLiteral(equals(true))),
-    hasTrueExpression(cxxBoolLiteral(equals(false))));
+  StatementMatcher Conditional =
+      conditionalOperator(hasCondition(cxxBoolLiteral(equals(true))),
+                          hasTrueExpression(cxxBoolLiteral(equals(false))));
 
   EXPECT_TRUE(matches("void x() { true ? false : true; }", Conditional));
   EXPECT_TRUE(notMatches("void x() { false ? false : true; }", Conditional));
   EXPECT_TRUE(notMatches("void x() { true ? true : false; }", Conditional));
 
-  StatementMatcher ConditionalFalse = conditionalOperator(
-    hasFalseExpression(cxxBoolLiteral(equals(false))));
+  StatementMatcher ConditionalFalse =
+      conditionalOperator(hasFalseExpression(cxxBoolLiteral(equals(false))));
 
   EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse));
   EXPECT_TRUE(
-    notMatches("void x() { true ? false : true; }", ConditionalFalse));
+      notMatches("void x() { true ? false : true; }", ConditionalFalse));
 
   EXPECT_TRUE(matches("void x() { true ? true : false; }", ConditionalFalse));
   EXPECT_TRUE(
-    notMatches("void x() { true ? false : true; }", ConditionalFalse));
+      notMatches("void x() { true ? false : true; }", ConditionalFalse));
 }
 
 TEST_P(ASTMatchersTest, BinaryConditionalOperator) {
@@ -1132,18 +1105,17 @@ TEST_P(ASTMatchersTest, BinaryConditionalOperator) {
   EXPECT_TRUE(matches("void x() { 1 ?: 0; }", AlwaysOne));
 
   StatementMatcher FourNotFive = binaryConditionalOperator(
-    hasTrueExpression(opaqueValueExpr(
-      hasSourceExpression((integerLiteral(equals(4)))))),
-    hasFalseExpression(integerLiteral(equals(5))));
+      hasTrueExpression(
+          opaqueValueExpr(hasSourceExpression((integerLiteral(equals(4)))))),
+      hasFalseExpression(integerLiteral(equals(5))));
 
   EXPECT_TRUE(matches("void x() { 4 ?: 5; }", FourNotFive));
 }
 
 TEST_P(ASTMatchersTest, ArraySubscriptExpr) {
-  EXPECT_TRUE(matches("int i[2]; void f() { i[1] = 1; }",
-                      arraySubscriptExpr()));
-  EXPECT_TRUE(notMatches("int i; void f() { i = 1; }",
-                         arraySubscriptExpr()));
+  EXPECT_TRUE(
+      matches("int i[2]; void f() { i[1] = 1; }", arraySubscriptExpr()));
+  EXPECT_TRUE(notMatches("int i; void f() { i = 1; }", arraySubscriptExpr()));
 }
 
 TEST_P(ASTMatchersTest, ForStmt) {
@@ -1178,10 +1150,9 @@ TEST_P(ASTMatchersTest, CompoundStatement_DoesNotMatchEmptyStruct) {
   }
   // It's not a compound statement just because there's "{}" in the source
   // text. This is an AST search, not grep.
-  EXPECT_TRUE(notMatches("namespace n { struct S {}; }",
-                         compoundStmt()));
-  EXPECT_TRUE(matches("namespace n { struct S { void f() {{}} }; }",
-                      compoundStmt()));
+  EXPECT_TRUE(notMatches("namespace n { struct S {}; }", compoundStmt()));
+  EXPECT_TRUE(
+      matches("namespace n { struct S { void f() {{}} }; }", compoundStmt()));
 }
 
 TEST_P(ASTMatchersTest, CastExpr_MatchesExplicitCasts) {
@@ -1242,8 +1213,8 @@ TEST_P(ASTMatchersTest, CXXReinterpretCastExpr_DoesNotMatchOtherCasts) {
   EXPECT_TRUE(notMatches("void* p = static_cast(&p);",
                          cxxReinterpretCastExpr()));
   EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
-                           "B b;"
-                           "D* p = dynamic_cast(&b);",
+                         "B b;"
+                         "D* p = dynamic_cast(&b);",
                          cxxReinterpretCastExpr()));
 }
 
@@ -1262,11 +1233,10 @@ TEST_P(ASTMatchersTest, CXXFunctionalCastExpr_DoesNotMatchOtherCasts) {
   }
   StringRef FooClass = "class Foo { public: Foo(const char*); };";
   EXPECT_TRUE(
-    notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\"; }",
-               cxxFunctionalCastExpr()));
-  EXPECT_TRUE(
-    notMatches(FooClass + "void r() { Foo f = \"hello world\"; }",
-               cxxFunctionalCastExpr()));
+      notMatches(FooClass + "void r() { Foo f = (Foo) \"hello world\"; }",
+                 cxxFunctionalCastExpr()));
+  EXPECT_TRUE(notMatches(FooClass + "void r() { Foo f = \"hello world\"; }",
+                         cxxFunctionalCastExpr()));
 }
 
 TEST_P(ASTMatchersTest, CXXDynamicCastExpr) {
@@ -1274,8 +1244,8 @@ TEST_P(ASTMatchersTest, CXXDynamicCastExpr) {
     return;
   }
   EXPECT_TRUE(matches("struct B { virtual ~B() {} }; struct D : B {};"
-                        "B b;"
-                        "D* p = dynamic_cast(&b);",
+                      "B b;"
+                      "D* p = dynamic_cast(&b);",
                       cxxDynamicCastExpr()));
 }
 
@@ -1283,8 +1253,7 @@ TEST_P(ASTMatchersTest, CXXStaticCastExpr_MatchesSimpleCase) {
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(matches("void* p(static_cast(&p));",
-                      cxxStaticCastExpr()));
+  EXPECT_TRUE(matches("void* p(static_cast(&p));", cxxStaticCastExpr()));
 }
 
 TEST_P(ASTMatchersTest, CXXStaticCastExpr_DoesNotMatchOtherCasts) {
@@ -1292,13 +1261,13 @@ TEST_P(ASTMatchersTest, CXXStaticCastExpr_DoesNotMatchOtherCasts) {
     return;
   }
   EXPECT_TRUE(notMatches("char* p = (char*)(&p);", cxxStaticCastExpr()));
-  EXPECT_TRUE(notMatches("char q, *p = const_cast(&q);",
-                         cxxStaticCastExpr()));
+  EXPECT_TRUE(
+      notMatches("char q, *p = const_cast(&q);", cxxStaticCastExpr()));
   EXPECT_TRUE(notMatches("void* p = reinterpret_cast(&p);",
                          cxxStaticCastExpr()));
   EXPECT_TRUE(notMatches("struct B { virtual ~B() {} }; struct D : B {};"
-                           "B b;"
-                           "D* p = dynamic_cast(&b);",
+                         "B b;"
+                         "D* p = dynamic_cast(&b);",
                          cxxStaticCastExpr()));
 }
 
@@ -1311,11 +1280,11 @@ TEST_P(ASTMatchersTest, CStyleCastExpr_DoesNotMatchOtherCasts) {
     return;
   }
   EXPECT_TRUE(notMatches("char* p = static_cast(0);"
-                           "char q, *r = const_cast(&q);"
-                           "void* s = reinterpret_cast(&s);"
-                           "struct B { virtual ~B() {} }; struct D : B {};"
-                           "B b;"
-                           "D* t = dynamic_cast(&b);",
+                         "char q, *r = const_cast(&q);"
+                         "void* s = reinterpret_cast(&s);"
+                         "struct B { virtual ~B() {} }; struct D : B {};"
+                         "B b;"
+                         "D* t = dynamic_cast(&b);",
                          cStyleCastExpr()));
 }
 
@@ -1335,12 +1304,12 @@ TEST_P(ASTMatchersTest, ImplicitCastExpr_MatchesSimpleCase) {
 }
 
 TEST_P(ASTMatchersTest, ImplicitCastExpr_DoesNotMatchIncorrectly) {
-  // This test verifies that implicitCastExpr() matches exactly when implicit casts
-  // are present, and that it ignores explicit and paren casts.
+  // This test verifies that implicitCastExpr() matches exactly when implicit
+  // casts are present, and that it ignores explicit and paren casts.
 
   // These two test cases have no casts.
-  EXPECT_TRUE(notMatches("int x = 0;",
-                         varDecl(hasInitializer(implicitCastExpr()))));
+  EXPECT_TRUE(
+      notMatches("int x = 0;", varDecl(hasInitializer(implicitCastExpr()))));
   EXPECT_TRUE(
       notMatches("int x = (0);", varDecl(hasInitializer(implicitCastExpr()))));
   EXPECT_TRUE(notMatches("void f() { int x = 0; double d = (double) x; }",
@@ -1393,7 +1362,7 @@ TEST_P(ASTMatchersTest, InitListExpr) {
   EXPECT_TRUE(matches("struct B { int x, y; }; struct B b = { 5, 6 };",
                       initListExpr(hasType(recordDecl(hasName("B"))))));
   EXPECT_TRUE(
-    matches("int i[1] = {42, [0] = 43};", integerLiteral(equals(42))));
+      matches("int i[1] = {42, [0] = 43};", integerLiteral(equals(42))));
 }
 
 TEST_P(ASTMatchersTest, InitListExpr_CXX) {
@@ -1441,8 +1410,7 @@ TEST_P(ASTMatchersTest, UsingDecl_MatchesUsingDeclarations) {
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(matches("namespace X { int x; } using X::x;",
-                      usingDecl()));
+  EXPECT_TRUE(matches("namespace X { int x; } using X::x;", usingDecl()));
 }
 
 TEST_P(ASTMatchersTest, UsingDecl_MatchesShadowUsingDelcarations) {
@@ -1460,7 +1428,7 @@ TEST_P(ASTMatchersTest, UsingDirectiveDecl_MatchesUsingNamespace) {
   EXPECT_TRUE(matches("namespace X { int x; } using namespace X;",
                       usingDirectiveDecl()));
   EXPECT_FALSE(
-    matches("namespace X { int x; } using X::x;", usingDirectiveDecl()));
+      matches("namespace X { int x; } using X::x;", usingDirectiveDecl()));
 }
 
 TEST_P(ASTMatchersTest, WhileStmt) {
@@ -1499,11 +1467,11 @@ TEST_P(ASTMatchersTest, CxxExceptionHandling_SimpleCases) {
   EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", cxxCatchStmt()));
   EXPECT_TRUE(matches("void foo() try { } catch(int X) { }", cxxTryStmt()));
   EXPECT_TRUE(
-    notMatches("void foo() try { } catch(int X) { }", cxxThrowExpr()));
-  EXPECT_TRUE(matches("void foo() try { throw; } catch(int X) { }",
-                      cxxThrowExpr()));
-  EXPECT_TRUE(matches("void foo() try { throw 5;} catch(int X) { }",
-                      cxxThrowExpr()));
+      notMatches("void foo() try { } catch(int X) { }", cxxThrowExpr()));
+  EXPECT_TRUE(
+      matches("void foo() try { throw; } catch(int X) { }", cxxThrowExpr()));
+  EXPECT_TRUE(
+      matches("void foo() try { throw 5;} catch(int X) { }", cxxThrowExpr()));
   EXPECT_TRUE(matches("void foo() try { throw; } catch(...) { }",
                       cxxCatchStmt(isCatchAll())));
   EXPECT_TRUE(notMatches("void foo() try { throw; } catch(int) { }",
@@ -1542,9 +1510,8 @@ TEST_P(ASTMatchersTest, QualType) {
 
 TEST_P(ASTMatchersTest, ConstantArrayType) {
   EXPECT_TRUE(matches("int a[2];", constantArrayType()));
-  EXPECT_TRUE(notMatches(
-    "void f() { int a[] = { 2, 3 }; int b[a[0]]; }",
-    constantArrayType(hasElementType(builtinType()))));
+  EXPECT_TRUE(notMatches("void f() { int a[] = { 2, 3 }; int b[a[0]]; }",
+                         constantArrayType(hasElementType(builtinType()))));
 
   EXPECT_TRUE(matches("int a[42];", constantArrayType(hasSize(42))));
   EXPECT_TRUE(matches("int b[2*21];", constantArrayType(hasSize(42))));
@@ -1555,12 +1522,12 @@ TEST_P(ASTMatchersTest, DependentSizedArrayType) {
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(matches(
-    "template  class array { T data[Size]; };",
-    dependentSizedArrayType()));
-  EXPECT_TRUE(notMatches(
-    "int a[42]; int b[] = { 2, 3 }; void f() { int c[b[0]]; }",
-    dependentSizedArrayType()));
+  EXPECT_TRUE(
+      matches("template  class array { T data[Size]; };",
+              dependentSizedArrayType()));
+  EXPECT_TRUE(
+      notMatches("int a[42]; int b[] = { 2, 3 }; void f() { int c[b[0]]; }",
+                 dependentSizedArrayType()));
 }
 
 TEST_P(ASTMatchersTest, IncompleteArrayType) {
@@ -1575,22 +1542,21 @@ TEST_P(ASTMatchersTest, VariableArrayType) {
   EXPECT_TRUE(matches("void f(int b) { int a[b]; }", variableArrayType()));
   EXPECT_TRUE(notMatches("int a[] = {2, 3}; int b[42];", variableArrayType()));
 
-  EXPECT_TRUE(matches(
-    "void f(int b) { int a[b]; }",
-    variableArrayType(hasSizeExpr(ignoringImpCasts(declRefExpr(to(
-      varDecl(hasName("b")))))))));
+  EXPECT_TRUE(matches("void f(int b) { int a[b]; }",
+                      variableArrayType(hasSizeExpr(ignoringImpCasts(
+                          declRefExpr(to(varDecl(hasName("b")))))))));
 }
 
 TEST_P(ASTMatchersTest, AtomicType) {
   if (llvm::Triple(llvm::sys::getDefaultTargetTriple()).getOS() !=
-    llvm::Triple::Win32) {
+      llvm::Triple::Win32) {
     // FIXME: Make this work for MSVC.
     EXPECT_TRUE(matches("_Atomic(int) i;", atomicType()));
 
-    EXPECT_TRUE(matches("_Atomic(int) i;",
-                        atomicType(hasValueType(isInteger()))));
-    EXPECT_TRUE(notMatches("_Atomic(float) f;",
-                           atomicType(hasValueType(isInteger()))));
+    EXPECT_TRUE(
+        matches("_Atomic(int) i;", atomicType(hasValueType(isInteger()))));
+    EXPECT_TRUE(
+        notMatches("_Atomic(float) f;", atomicType(hasValueType(isInteger()))));
   }
 }
 
@@ -1608,9 +1574,9 @@ TEST_P(ASTMatchersTest, AutoType) {
 
   // FIXME: Matching against the type-as-written can't work here, because the
   //        type as written was not deduced.
-  //EXPECT_TRUE(matches("auto a = 1;",
+  // EXPECT_TRUE(matches("auto a = 1;",
   //                    autoType(hasDeducedType(isInteger()))));
-  //EXPECT_TRUE(notMatches("auto b = 2.0;",
+  // EXPECT_TRUE(notMatches("auto b = 2.0;",
   //                       autoType(hasDeducedType(isInteger()))));
 }
 
@@ -1657,48 +1623,43 @@ TEST_P(ASTMatchersTest, FunctionProtoType_CXX) {
 
 TEST_P(ASTMatchersTest, ParenType) {
   EXPECT_TRUE(
-    matches("int (*array)[4];", varDecl(hasType(pointsTo(parenType())))));
+      matches("int (*array)[4];", varDecl(hasType(pointsTo(parenType())))));
   EXPECT_TRUE(notMatches("int *array[4];", varDecl(hasType(parenType()))));
 
   EXPECT_TRUE(matches(
-    "int (*ptr_to_func)(int);",
-    varDecl(hasType(pointsTo(parenType(innerType(functionType())))))));
+      "int (*ptr_to_func)(int);",
+      varDecl(hasType(pointsTo(parenType(innerType(functionType())))))));
   EXPECT_TRUE(notMatches(
-    "int (*ptr_to_array)[4];",
-    varDecl(hasType(pointsTo(parenType(innerType(functionType())))))));
+      "int (*ptr_to_array)[4];",
+      varDecl(hasType(pointsTo(parenType(innerType(functionType())))))));
 }
 
 TEST_P(ASTMatchersTest, PointerType) {
   // FIXME: Reactive when these tests can be more specific (not matching
   // implicit code on certain platforms), likely when we have hasDescendant for
   // Types/TypeLocs.
-  //EXPECT_TRUE(matchAndVerifyResultTrue(
+  // EXPECT_TRUE(matchAndVerifyResultTrue(
   //    "int* a;",
   //    pointerTypeLoc(pointeeLoc(typeLoc().bind("loc"))),
   //    std::make_unique>("loc", 1)));
-  //EXPECT_TRUE(matchAndVerifyResultTrue(
+  // EXPECT_TRUE(matchAndVerifyResultTrue(
   //    "int* a;",
   //    pointerTypeLoc().bind("loc"),
   //    std::make_unique>("loc", 1)));
-  EXPECT_TRUE(matches(
-    "int** a;",
-    loc(pointerType(pointee(qualType())))));
-  EXPECT_TRUE(matches(
-    "int** a;",
-    loc(pointerType(pointee(pointerType())))));
-  EXPECT_TRUE(matches(
-    "int* b; int* * const a = &b;",
-    loc(qualType(isConstQualified(), pointerType()))));
+  EXPECT_TRUE(matches("int** a;", loc(pointerType(pointee(qualType())))));
+  EXPECT_TRUE(matches("int** a;", loc(pointerType(pointee(pointerType())))));
+  EXPECT_TRUE(matches("int* b; int* * const a = &b;",
+                      loc(qualType(isConstQualified(), pointerType()))));
 
   StringRef Fragment = "int *ptr;";
-  EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
-                                           hasType(blockPointerType()))));
-  EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
-                                           hasType(memberPointerType()))));
-  EXPECT_TRUE(matches(Fragment, varDecl(hasName("ptr"),
-                                        hasType(pointerType()))));
-  EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("ptr"),
-                                           hasType(referenceType()))));
+  EXPECT_TRUE(notMatches(Fragment,
+                         varDecl(hasName("ptr"), hasType(blockPointerType()))));
+  EXPECT_TRUE(notMatches(
+      Fragment, varDecl(hasName("ptr"), hasType(memberPointerType()))));
+  EXPECT_TRUE(
+      matches(Fragment, varDecl(hasName("ptr"), hasType(pointerType()))));
+  EXPECT_TRUE(
+      notMatches(Fragment, varDecl(hasName("ptr"), hasType(referenceType()))));
 }
 
 TEST_P(ASTMatchersTest, PointerType_CXX) {
@@ -1763,28 +1724,28 @@ TEST_P(ASTMatchersTest, AutoRefTypes) {
                        "auto &c = a;"
                        "auto &&d = c;"
                        "auto &&e = 2;";
-  EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("a"),
-                                           hasType(referenceType()))));
-  EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("b"),
-                                           hasType(referenceType()))));
-  EXPECT_TRUE(matches(Fragment, varDecl(hasName("c"),
-                                        hasType(referenceType()))));
-  EXPECT_TRUE(matches(Fragment, varDecl(hasName("c"),
-                                        hasType(lValueReferenceType()))));
-  EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("c"),
-                                           hasType(rValueReferenceType()))));
-  EXPECT_TRUE(matches(Fragment, varDecl(hasName("d"),
-                                        hasType(referenceType()))));
-  EXPECT_TRUE(matches(Fragment, varDecl(hasName("d"),
-                                        hasType(lValueReferenceType()))));
-  EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("d"),
-                                           hasType(rValueReferenceType()))));
-  EXPECT_TRUE(matches(Fragment, varDecl(hasName("e"),
-                                        hasType(referenceType()))));
-  EXPECT_TRUE(notMatches(Fragment, varDecl(hasName("e"),
-                                           hasType(lValueReferenceType()))));
-  EXPECT_TRUE(matches(Fragment, varDecl(hasName("e"),
-                                        hasType(rValueReferenceType()))));
+  EXPECT_TRUE(
+      notMatches(Fragment, varDecl(hasName("a"), hasType(referenceType()))));
+  EXPECT_TRUE(
+      notMatches(Fragment, varDecl(hasName("b"), hasType(referenceType()))));
+  EXPECT_TRUE(
+      matches(Fragment, varDecl(hasName("c"), hasType(referenceType()))));
+  EXPECT_TRUE(
+      matches(Fragment, varDecl(hasName("c"), hasType(lValueReferenceType()))));
+  EXPECT_TRUE(notMatches(
+      Fragment, varDecl(hasName("c"), hasType(rValueReferenceType()))));
+  EXPECT_TRUE(
+      matches(Fragment, varDecl(hasName("d"), hasType(referenceType()))));
+  EXPECT_TRUE(
+      matches(Fragment, varDecl(hasName("d"), hasType(lValueReferenceType()))));
+  EXPECT_TRUE(notMatches(
+      Fragment, varDecl(hasName("d"), hasType(rValueReferenceType()))));
+  EXPECT_TRUE(
+      matches(Fragment, varDecl(hasName("e"), hasType(referenceType()))));
+  EXPECT_TRUE(notMatches(
+      Fragment, varDecl(hasName("e"), hasType(lValueReferenceType()))));
+  EXPECT_TRUE(
+      matches(Fragment, varDecl(hasName("e"), hasType(rValueReferenceType()))));
 }
 
 TEST_P(ASTMatchersTest, EnumType) {
@@ -1796,34 +1757,29 @@ TEST_P(ASTMatchersTest, EnumType_CXX) {
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(matches("enum Color { Green }; Color color;",
-                      loc(enumType())));
+  EXPECT_TRUE(matches("enum Color { Green }; Color color;", loc(enumType())));
 }
 
 TEST_P(ASTMatchersTest, EnumType_CXX11) {
   if (!GetParam().isCXX11OrLater()) {
     return;
   }
-  EXPECT_TRUE(matches("enum class Color { Green }; Color color;",
-                      loc(enumType())));
+  EXPECT_TRUE(
+      matches("enum class Color { Green }; Color color;", loc(enumType())));
 }
 
 TEST_P(ASTMatchersTest, PointerType_MatchesPointersToConstTypes) {
-  EXPECT_TRUE(matches("int b; int * const a = &b;",
-                      loc(pointerType())));
-  EXPECT_TRUE(matches("int b; int * const a = &b;",
-                      loc(pointerType())));
-  EXPECT_TRUE(matches(
-    "int b; const int * a = &b;",
-    loc(pointerType(pointee(builtinType())))));
-  EXPECT_TRUE(matches(
-    "int b; const int * a = &b;",
-    pointerType(pointee(builtinType()))));
+  EXPECT_TRUE(matches("int b; int * const a = &b;", loc(pointerType())));
+  EXPECT_TRUE(matches("int b; int * const a = &b;", loc(pointerType())));
+  EXPECT_TRUE(matches("int b; const int * a = &b;",
+                      loc(pointerType(pointee(builtinType())))));
+  EXPECT_TRUE(matches("int b; const int * a = &b;",
+                      pointerType(pointee(builtinType()))));
 }
 
 TEST_P(ASTMatchersTest, TypedefType) {
-  EXPECT_TRUE(matches("typedef int X; X a;", varDecl(hasName("a"),
-                                                     hasType(typedefType()))));
+  EXPECT_TRUE(matches("typedef int X; X a;",
+                      varDecl(hasName("a"), hasType(typedefType()))));
 }
 
 TEST_P(ASTMatchersTest, TemplateSpecializationType) {
@@ -1864,13 +1820,13 @@ TEST_P(ASTMatchersTest, ElaboratedType) {
     // FIXME: Add a test for `elaboratedType()` that does not depend on C++.
     return;
   }
-  EXPECT_TRUE(matches(
-    "namespace N {"
-      "  namespace M {"
-      "    class D {};"
-      "  }"
-      "}"
-      "N::M::D d;", elaboratedType()));
+  EXPECT_TRUE(matches("namespace N {"
+                      "  namespace M {"
+                      "    class D {};"
+                      "  }"
+                      "}"
+                      "N::M::D d;",
+                      elaboratedType()));
   EXPECT_TRUE(matches("class C {} c;", elaboratedType()));
   EXPECT_TRUE(notMatches("class C {}; C c;", elaboratedType()));
 }
@@ -1885,30 +1841,29 @@ TEST_P(ASTMatchersTest, SubstTemplateTypeParmType) {
                    "}"
                    "int i = F();";
   EXPECT_FALSE(matches(code, binaryOperator(hasLHS(
-    expr(hasType(substTemplateTypeParmType()))))));
+                                 expr(hasType(substTemplateTypeParmType()))))));
   EXPECT_TRUE(matches(code, binaryOperator(hasRHS(
-    expr(hasType(substTemplateTypeParmType()))))));
+                                expr(hasType(substTemplateTypeParmType()))))));
 }
 
 TEST_P(ASTMatchersTest, NestedNameSpecifier) {
   if (!GetParam().isCXX()) {
     return;
   }
-  EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;",
-                      nestedNameSpecifier()));
+  EXPECT_TRUE(
+      matches("namespace ns { struct A {}; } ns::A a;", nestedNameSpecifier()));
   EXPECT_TRUE(matches("template  class A { typename T::B b; };",
                       nestedNameSpecifier()));
-  EXPECT_TRUE(matches("struct A { void f(); }; void A::f() {}",
-                      nestedNameSpecifier()));
+  EXPECT_TRUE(
+      matches("struct A { void f(); }; void A::f() {}", nestedNameSpecifier()));
   EXPECT_TRUE(matches("namespace a { namespace b {} } namespace ab = a::b;",
                       nestedNameSpecifier()));
 
-  EXPECT_TRUE(matches(
-    "struct A { static void f() {} }; void g() { A::f(); }",
-    nestedNameSpecifier()));
-  EXPECT_TRUE(notMatches(
-    "struct A { static void f() {} }; void g(A* a) { a->f(); }",
-    nestedNameSpecifier()));
+  EXPECT_TRUE(matches("struct A { static void f() {} }; void g() { A::f(); }",
+                      nestedNameSpecifier()));
+  EXPECT_TRUE(
+      notMatches("struct A { static void f() {} }; void g(A* a) { a->f(); }",
+                 nestedNameSpecifier()));
 }
 
 TEST_P(ASTMatchersTest, NullStmt) {
@@ -1929,10 +1884,10 @@ TEST_P(ASTMatchersTest, NestedNameSpecifier_MatchesTypes) {
     return;
   }
   NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
-    specifiesType(hasDeclaration(recordDecl(hasName("A")))));
+      specifiesType(hasDeclaration(recordDecl(hasName("A")))));
   EXPECT_TRUE(matches("struct A { struct B {}; }; A::B b;", Matcher));
-  EXPECT_TRUE(matches("struct A { struct B { struct C {}; }; }; A::B::C c;",
-                      Matcher));
+  EXPECT_TRUE(
+      matches("struct A { struct B { struct C {}; }; }; A::B::C c;", Matcher));
   EXPECT_TRUE(notMatches("namespace A { struct B {}; } A::B b;", Matcher));
 }
 
@@ -1940,8 +1895,8 @@ TEST_P(ASTMatchersTest, NestedNameSpecifier_MatchesNamespaceDecls) {
   if (!GetParam().isCXX()) {
     return;
   }
-  NestedNameSpecifierMatcher Matcher = nestedNameSpecifier(
-    specifiesNamespace(hasName("ns")));
+  NestedNameSpecifierMatcher Matcher =
+      nestedNameSpecifier(specifiesNamespace(hasName("ns")));
   EXPECT_TRUE(matches("namespace ns { struct A {}; } ns::A a;", Matcher));
   EXPECT_TRUE(notMatches("namespace xx { struct A {}; } xx::A a;", Matcher));
   EXPECT_TRUE(notMatches("struct ns { struct A {}; }; ns::A a;", Matcher));
@@ -1953,16 +1908,15 @@ TEST_P(ASTMatchersTest,
     return;
   }
   EXPECT_TRUE(matches(
-    "struct A { struct B { struct C {}; }; }; A::B::C c;",
-    nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A"))))));
-  EXPECT_TRUE(matches(
-    "struct A { struct B { struct C {}; }; }; A::B::C c;",
-    nestedNameSpecifierLoc(hasPrefix(
-      specifiesTypeLoc(loc(qualType(asString("struct A"))))))));
+      "struct A { struct B { struct C {}; }; }; A::B::C c;",
+      nestedNameSpecifier(hasPrefix(specifiesType(asString("struct A"))))));
+  EXPECT_TRUE(matches("struct A { struct B { struct C {}; }; }; A::B::C c;",
+                      nestedNameSpecifierLoc(hasPrefix(specifiesTypeLoc(
+                          loc(qualType(asString("struct A"))))))));
   EXPECT_TRUE(matches(
-    "namespace N { struct A { struct B { struct C {}; }; }; } N::A::B::C c;",
-    nestedNameSpecifierLoc(hasPrefix(
-      specifiesTypeLoc(loc(qualType(asString("struct N::A"))))))));
+      "namespace N { struct A { struct B { struct C {}; }; }; } N::A::B::C c;",
+      nestedNameSpecifierLoc(hasPrefix(
+          specifiesTypeLoc(loc(qualType(asString("struct N::A"))))))));
 }
 
 template 
@@ -1980,18 +1934,18 @@ class VerifyAncestorHasChildIsEqual : public BoundNodesCallback {
     // to equalsNode.
     const T *TypedNode = cast(Node);
     return selectFirst(
-      "", match(stmt(hasParent(
-        stmt(has(stmt(equalsNode(TypedNode)))).bind(""))),
-                *Node, Context)) != nullptr;
+               "", match(stmt(hasParent(
+                             stmt(has(stmt(equalsNode(TypedNode)))).bind(""))),
+                         *Node, Context)) != nullptr;
   }
   bool verify(const BoundNodes &Nodes, ASTContext &Context, const Decl *Node) {
     // Use the original typed pointer to verify we can pass pointers to subtypes
     // to equalsNode.
     const T *TypedNode = cast(Node);
     return selectFirst(
-      "", match(decl(hasParent(
-        decl(has(decl(equalsNode(TypedNode)))).bind(""))),
-                *Node, Context)) != nullptr;
+               "", match(decl(hasParent(
+                             decl(has(decl(equalsNode(TypedNode)))).bind(""))),
+                         *Node, Context)) != nullptr;
   }
   bool verify(const BoundNodes &Nodes, ASTContext &Context, const Type *Node) {
     // Use the original typed pointer to verify we can pass pointers to subtypes
@@ -1999,9 +1953,9 @@ class VerifyAncestorHasChildIsEqual : public BoundNodesCallback {
     const T *TypedNode = cast(Node);
     const auto *Dec = Nodes.getNodeAs("decl");
     return selectFirst(
-      "", match(fieldDecl(hasParent(decl(has(fieldDecl(
-        hasType(type(equalsNode(TypedNode)).bind(""))))))),
-                *Dec, Context)) != nullptr;
+               "", match(fieldDecl(hasParent(decl(has(fieldDecl(
+                             hasType(type(equalsNode(TypedNode)).bind(""))))))),
+                         *Dec, Context)) != nullptr;
   }
 };
 
@@ -2100,43 +2054,31 @@ TEST(ASTMatchersTestObjC, ObjCMessageExpr) {
                           "  Str *up = [text uppercaseString];"
                           "} "
                           "@end ";
-  EXPECT_TRUE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(anything())));
+  EXPECT_TRUE(matchesObjC(Objc1String, objcMessageExpr(anything())));
   EXPECT_TRUE(matchesObjC(Objc1String,
-                          objcMessageExpr(hasAnySelector({
-                                          "contents", "meth:"}))
+                          objcMessageExpr(hasAnySelector({"contents", "meth:"}))
 
-                         ));
-  EXPECT_TRUE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(hasSelector("contents"))));
-  EXPECT_TRUE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(hasAnySelector("contents", "contentsA"))));
-  EXPECT_FALSE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(hasAnySelector("contentsB", "contentsC"))));
+                              ));
+  EXPECT_TRUE(
+      matchesObjC(Objc1String, objcMessageExpr(hasSelector("contents"))));
   EXPECT_TRUE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(matchesSelector("cont*"))));
+      Objc1String, objcMessageExpr(hasAnySelector("contents", "contentsA"))));
   EXPECT_FALSE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(matchesSelector("?cont*"))));
-  EXPECT_TRUE(notMatchesObjC(
-    Objc1String,
-    objcMessageExpr(hasSelector("contents"), hasNullSelector())));
-  EXPECT_TRUE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(hasSelector("contents"), hasUnarySelector())));
-  EXPECT_TRUE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(hasSelector("contents"), numSelectorArgs(0))));
-  EXPECT_TRUE(matchesObjC(
-    Objc1String,
-    objcMessageExpr(matchesSelector("uppercase*"),
-                    argumentCountIs(0)
-    )));
+      Objc1String, objcMessageExpr(hasAnySelector("contentsB", "contentsC"))));
+  EXPECT_TRUE(
+      matchesObjC(Objc1String, objcMessageExpr(matchesSelector("cont*"))));
+  EXPECT_FALSE(
+      matchesObjC(Objc1String, objcMessageExpr(matchesSelector("?cont*"))));
+  EXPECT_TRUE(
+      notMatchesObjC(Objc1String, objcMessageExpr(hasSelector("contents"),
+                                                  hasNullSelector())));
+  EXPECT_TRUE(matchesObjC(Objc1String, objcMessageExpr(hasSelector("contents"),
+                                                       hasUnarySelector())));
+  EXPECT_TRUE(matchesObjC(Objc1String, objcMessageExpr(hasSelector("contents"),
+                                                       numSelectorArgs(0))));
+  EXPECT_TRUE(
+      matchesObjC(Objc1String, objcMessageExpr(matchesSelector("uppercase*"),
+                                               argumentCountIs(0))));
 }
 
 TEST(ASTMatchersTestObjC, ObjCDecls) {
@@ -2157,33 +2099,17 @@ TEST(ASTMatchersTestObjC, ObjCDecls) {
                          "- (void)abc_doThing {} "
                          "@end ";
 
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcProtocolDecl(hasName("Proto"))));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcImplementationDecl(hasName("Thing"))));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcCategoryDecl(hasName("ABC"))));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcCategoryImplDecl(hasName("ABC"))));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcMethodDecl(hasName("protoDidThing"))));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcMethodDecl(hasName("abc_doThing"))));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcMethodDecl(hasName("anything"))));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcIvarDecl(hasName("_ivar"))));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcPropertyDecl(hasName("enabled"))));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcProtocolDecl(hasName("Proto"))));
+  EXPECT_TRUE(
+      matchesObjC(ObjCString, objcImplementationDecl(hasName("Thing"))));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcCategoryDecl(hasName("ABC"))));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcCategoryImplDecl(hasName("ABC"))));
+  EXPECT_TRUE(
+      matchesObjC(ObjCString, objcMethodDecl(hasName("protoDidThing"))));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcMethodDecl(hasName("abc_doThing"))));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcMethodDecl(hasName("anything"))));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcIvarDecl(hasName("_ivar"))));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcPropertyDecl(hasName("enabled"))));
 }
 
 TEST(ASTMatchersTestObjC, ObjCExceptionStmts) {
@@ -2194,18 +2120,10 @@ TEST(ASTMatchersTestObjC, ObjCExceptionStmts) {
                          "  } @finally {}"
                          "}";
 
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcTryStmt()));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcThrowStmt()));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcCatchStmt()));
-  EXPECT_TRUE(matchesObjC(
-    ObjCString,
-    objcFinallyStmt()));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcTryStmt()));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcThrowStmt()));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcCatchStmt()));
+  EXPECT_TRUE(matchesObjC(ObjCString, objcFinallyStmt()));
 }
 
 TEST(ASTMatchersTestObjC, ObjCAutoreleasePoolStmt) {
@@ -2274,11 +2192,18 @@ void x() {
   EXPECT_TRUE(matchesWithOpenMP(Source3, Matcher));
 
   StringRef Source4 = R"(
+void x() {
+#pragma omp parallel default(firstprivate)
+;
+})";
+  EXPECT_TRUE(matchesWithOpenMP51(Source4, Matcher));
+
+  StringRef Source5 = R"(
 void x(int x) {
 #pragma omp parallel num_threads(x)
 ;
 })";
-  EXPECT_TRUE(notMatchesWithOpenMP(Source4, Matcher));
+  EXPECT_TRUE(notMatchesWithOpenMP(Source5, Matcher));
 }
 
 TEST(ASTMatchersTest, Finder_DynamicOnlyAcceptsSomeMatchers) {
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h
index 8669ebd552c83..bde6297f82ddc 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h
@@ -20,10 +20,10 @@ namespace clang {
 namespace ast_matchers {
 
 using clang::tooling::buildASTFromCodeWithArgs;
+using clang::tooling::FileContentMappings;
+using clang::tooling::FrontendActionFactory;
 using clang::tooling::newFrontendActionFactory;
 using clang::tooling::runToolOnCodeWithArgs;
-using clang::tooling::FrontendActionFactory;
-using clang::tooling::FileContentMappings;
 
 class BoundNodesCallback {
 public:
@@ -38,7 +38,8 @@ class BoundNodesCallback {
 // If 'FindResultVerifier' is NULL, sets *Verified to true when Run is called.
 class VerifyMatch : public MatchFinder::MatchCallback {
 public:
-  VerifyMatch(std::unique_ptr FindResultVerifier, bool *Verified)
+  VerifyMatch(std::unique_ptr FindResultVerifier,
+              bool *Verified)
       : Verified(Verified), FindResultReviewer(std::move(FindResultVerifier)) {}
 
   void run(const MatchFinder::MatchResult &Result) override {
@@ -124,17 +125,16 @@ testing::AssertionResult matchesConditionally(
     return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
   }
   if (Found != DynamicFound) {
-    return testing::AssertionFailure() << "Dynamic match result ("
-                                       << DynamicFound
-                                       << ") does not match static result ("
-                                       << Found << ")";
+    return testing::AssertionFailure()
+           << "Dynamic match result (" << DynamicFound
+           << ") does not match static result (" << Found << ")";
   }
   if (!Found && ExpectMatch) {
     return testing::AssertionFailure()
-      << "Could not find match in \"" << Code << "\"";
+           << "Could not find match in \"" << Code << "\"";
   } else if (Found && !ExpectMatch) {
     return testing::AssertionFailure()
-      << "Found unexpected match in \"" << Code << "\"";
+           << "Found unexpected match in \"" << Code << "\"";
   }
   return testing::AssertionSuccess();
 }
@@ -216,7 +216,8 @@ matchesConditionallyWithCuda(const Twine &Code, const T &AMatcher,
       "                      size_t sharedSize = 0,"
       "                      cudaStream_t stream = 0);"
       "extern \"C\" unsigned __cudaPushCallConfiguration("
-      "    dim3 gridDim, dim3 blockDim, size_t sharedMem = 0, void *stream = 0);";
+      "    dim3 gridDim, dim3 blockDim, size_t sharedMem = 0, void *stream = "
+      "0);";
 
   bool Found = false, DynamicFound = false;
   MatchFinder Finder;
@@ -233,22 +234,20 @@ matchesConditionallyWithCuda(const Twine &Code, const T &AMatcher,
   std::vector Args = {
       "-xcuda",  "-fno-ms-extensions",     "--cuda-host-only",     "-nocudainc",
       "-target", "x86_64-unknown-unknown", std::string(CompileArg)};
-  if (!runToolOnCodeWithArgs(Factory->create(),
-                             CudaHeader + Code, Args)) {
+  if (!runToolOnCodeWithArgs(Factory->create(), CudaHeader + Code, Args)) {
     return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
   }
   if (Found != DynamicFound) {
-    return testing::AssertionFailure() << "Dynamic match result ("
-                                       << DynamicFound
-                                       << ") does not match static result ("
-                                       << Found << ")";
+    return testing::AssertionFailure()
+           << "Dynamic match result (" << DynamicFound
+           << ") does not match static result (" << Found << ")";
   }
   if (!Found && ExpectMatch) {
     return testing::AssertionFailure()
-      << "Could not find match in \"" << Code << "\"";
+           << "Could not find match in \"" << Code << "\"";
   } else if (Found && !ExpectMatch) {
     return testing::AssertionFailure()
-      << "Found unexpected match in \"" << Code << "\"";
+           << "Found unexpected match in \"" << Code << "\"";
   }
   return testing::AssertionSuccess();
 }
@@ -276,13 +275,28 @@ testing::AssertionResult notMatchesWithOpenMP(const Twine &Code,
   return matchesConditionally(Code, AMatcher, false, {"-fopenmp=libomp"});
 }
 
+template 
+testing::AssertionResult matchesWithOpenMP51(const Twine &Code,
+                                             const T &AMatcher) {
+  return matchesConditionally(Code, AMatcher, true,
+                              {"-fopenmp=libomp", "-fopenmp-version=51"});
+}
+
+template 
+testing::AssertionResult notMatchesWithOpenMP51(const Twine &Code,
+                                                const T &AMatcher) {
+  return matchesConditionally(Code, AMatcher, false,
+                              {"-fopenmp=libomp", "-fopenmp-version=51"});
+}
+
 template 
 testing::AssertionResult matchAndVerifyResultConditionally(
     const Twine &Code, const T &AMatcher,
     std::unique_ptr FindResultVerifier, bool ExpectResult) {
   bool VerifiedResult = false;
   MatchFinder Finder;
-  VerifyMatch VerifyVerifiedResult(std::move(FindResultVerifier), &VerifiedResult);
+  VerifyMatch VerifyVerifiedResult(std::move(FindResultVerifier),
+                                   &VerifiedResult);
   Finder.addMatcher(AMatcher, &VerifyVerifiedResult);
   std::unique_ptr Factory(
       newFrontendActionFactory(&Finder));
@@ -296,10 +310,10 @@ testing::AssertionResult matchAndVerifyResultConditionally(
   }
   if (!VerifiedResult && ExpectResult) {
     return testing::AssertionFailure()
-      << "Could not verify result in \"" << Code << "\"";
+           << "Could not verify result in \"" << Code << "\"";
   } else if (VerifiedResult && !ExpectResult) {
     return testing::AssertionFailure()
-      << "Verified unexpected result in \"" << Code << "\"";
+           << "Verified unexpected result in \"" << Code << "\"";
   }
 
   VerifiedResult = false;
@@ -307,15 +321,15 @@ testing::AssertionResult matchAndVerifyResultConditionally(
   std::unique_ptr AST(
       buildASTFromCodeWithArgs(Code.toStringRef(Buffer), Args));
   if (!AST.get())
-    return testing::AssertionFailure() << "Parsing error in \"" << Code
-                                       << "\" while building AST";
+    return testing::AssertionFailure()
+           << "Parsing error in \"" << Code << "\" while building AST";
   Finder.matchAST(AST->getASTContext());
   if (!VerifiedResult && ExpectResult) {
     return testing::AssertionFailure()
-      << "Could not verify result in \"" << Code << "\" with AST";
+           << "Could not verify result in \"" << Code << "\" with AST";
   } else if (VerifiedResult && !ExpectResult) {
     return testing::AssertionFailure()
-      << "Verified unexpected result in \"" << Code << "\" with AST";
+           << "Verified unexpected result in \"" << Code << "\" with AST";
   }
 
   return testing::AssertionSuccess();
@@ -327,8 +341,8 @@ template 
 testing::AssertionResult matchAndVerifyResultTrue(
     const Twine &Code, const T &AMatcher,
     std::unique_ptr FindResultVerifier) {
-  return matchAndVerifyResultConditionally(
-      Code, AMatcher, std::move(FindResultVerifier), true);
+  return matchAndVerifyResultConditionally(Code, AMatcher,
+                                           std::move(FindResultVerifier), true);
 }
 
 template 
@@ -342,8 +356,7 @@ testing::AssertionResult matchAndVerifyResultFalse(
 // Implements a run method that returns whether BoundNodes contains a
 // Decl bound to Id that can be dynamically cast to T.
 // Optionally checks that the check succeeded a specific number of times.
-template 
-class VerifyIdIsBoundTo : public BoundNodesCallback {
+template  class VerifyIdIsBoundTo : public BoundNodesCallback {
 public:
   // Create an object that checks that a node of type \c T was bound to \c Id.
   // Does not check for a certain number of matches.
@@ -386,7 +399,7 @@ class VerifyIdIsBoundTo : public BoundNodesCallback {
       if (const NamedDecl *Named = Nodes->getNodeAs(Id)) {
         Name = Named->getNameAsString();
       } else if (const NestedNameSpecifier *NNS =
-        Nodes->getNodeAs(Id)) {
+                     Nodes->getNodeAs(Id)) {
         llvm::raw_string_ostream OS(Name);
         NNS->print(OS, PrintingPolicy(LangOptions()));
       }
@@ -398,7 +411,7 @@ class VerifyIdIsBoundTo : public BoundNodesCallback {
       return true;
     }
     EXPECT_TRUE(M.count(Id) == 0 ||
-      M.find(Id)->second.template get() == nullptr);
+                M.find(Id)->second.template get() == nullptr);
     return false;
   }
 
@@ -437,4 +450,4 @@ class ASTMatchersTest : public ::testing::Test,
 } // namespace ast_matchers
 } // namespace clang
 
-#endif  // LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H
+#endif // LLVM_CLANG_UNITTESTS_AST_MATCHERS_AST_MATCHERS_TEST_H
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
index bf799a781ae17..93ea63c1c2e60 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def
@@ -982,6 +982,7 @@ __OMP_CANCEL_KIND(taskgroup, 4)
 
 __OMP_DEFAULT_KIND(none)
 __OMP_DEFAULT_KIND(shared)
+__OMP_DEFAULT_KIND(firstprivate)
 __OMP_DEFAULT_KIND(unknown)
 
 #undef __OMP_DEFAULT_KIND

From 4d5fd0ee5ebda8979a448f5de397e3f1321b1ca8 Mon Sep 17 00:00:00 2001
From: Fangrui Song 
Date: Sun, 12 Jul 2020 21:04:31 -0700
Subject: [PATCH 065/771] [MC][RISCV] Set UseIntegratedAssembler to true

to align with most other targets. Also, -fintegrated-as is the default
for clang -target riscv*.
---
 llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp | 1 -
 llvm/test/CodeGen/RISCV/branch-relaxation.ll          | 4 ++--
 llvm/test/CodeGen/RISCV/inline-asm-abi-names.ll       | 4 ++--
 llvm/test/CodeGen/RISCV/inline-asm.ll                 | 4 ++--
 llvm/test/CodeGen/RISCV/large-stack.ll                | 4 ++++
 5 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
index 8db1738566ac8..089a2def4c210 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
@@ -27,7 +27,6 @@ RISCVMCAsmInfo::RISCVMCAsmInfo(const Triple &TT) {
   ExceptionsType = ExceptionHandling::DwarfCFI;
   Data16bitsDirective = "\t.half\t";
   Data32bitsDirective = "\t.word\t";
-  UseIntegratedAssembler = false;
 }
 
 const MCExpr *RISCVMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
diff --git a/llvm/test/CodeGen/RISCV/branch-relaxation.ll b/llvm/test/CodeGen/RISCV/branch-relaxation.ll
index 56f0f27a06488..3d617bf0b26b4 100644
--- a/llvm/test/CodeGen/RISCV/branch-relaxation.ll
+++ b/llvm/test/CodeGen/RISCV/branch-relaxation.ll
@@ -11,7 +11,7 @@ define void @relax_bcc(i1 %a) nounwind {
 ; CHECK-NEXT:    j .LBB0_2
 ; CHECK-NEXT:  .LBB0_1: # %iftrue
 ; CHECK-NEXT:    #APP
-; CHECK-NEXT:    .space 4096
+; CHECK-NEXT:    .zero 4096
 ; CHECK-NEXT:    #NO_APP
 ; CHECK-NEXT:  .LBB0_2: # %tail
 ; CHECK-NEXT:    ret
@@ -38,7 +38,7 @@ define i32 @relax_jal(i1 %a) nounwind {
 ; CHECK-NEXT:    #APP
 ; CHECK-NEXT:    #NO_APP
 ; CHECK-NEXT:    #APP
-; CHECK-NEXT:    .space 1048576
+; CHECK-NEXT:    .zero 1048576
 ; CHECK-NEXT:    #NO_APP
 ; CHECK-NEXT:    addi a0, zero, 1
 ; CHECK-NEXT:    ret
diff --git a/llvm/test/CodeGen/RISCV/inline-asm-abi-names.ll b/llvm/test/CodeGen/RISCV/inline-asm-abi-names.ll
index 4d85e3ea006b8..f9ed4aed6ca32 100644
--- a/llvm/test/CodeGen/RISCV/inline-asm-abi-names.ll
+++ b/llvm/test/CodeGen/RISCV/inline-asm-abi-names.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs -no-integrated-as < %s \
 ; RUN:   | FileCheck -check-prefix=RV32I %s
-; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs -no-integrated-as < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I %s
 
 ; These test that we can use both the architectural names (x*) and the ABI names
diff --git a/llvm/test/CodeGen/RISCV/inline-asm.ll b/llvm/test/CodeGen/RISCV/inline-asm.ll
index 43f951e352a68..de5d9a5f22a83 100644
--- a/llvm/test/CodeGen/RISCV/inline-asm.ll
+++ b/llvm/test/CodeGen/RISCV/inline-asm.ll
@@ -1,7 +1,7 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs -no-integrated-as < %s \
 ; RUN:   | FileCheck -check-prefix=RV32I %s
-; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs -no-integrated-as < %s \
 ; RUN:   | FileCheck -check-prefix=RV64I %s
 
 @gi = external global i32
diff --git a/llvm/test/CodeGen/RISCV/large-stack.ll b/llvm/test/CodeGen/RISCV/large-stack.ll
index 7acf0f4076e85..7cc6e83d7d85c 100644
--- a/llvm/test/CodeGen/RISCV/large-stack.ll
+++ b/llvm/test/CodeGen/RISCV/large-stack.ll
@@ -64,10 +64,12 @@ define void @test_emergency_spill_slot(i32 %a) {
 ; RV32I-FPELIM-NEXT:    add a1, a2, a1
 ; RV32I-FPELIM-NEXT:    #APP
 ; RV32I-FPELIM-NEXT:    nop
+; RV32I-FPELIM-EMPTY:
 ; RV32I-FPELIM-NEXT:    #NO_APP
 ; RV32I-FPELIM-NEXT:    sw a0, 0(a1)
 ; RV32I-FPELIM-NEXT:    #APP
 ; RV32I-FPELIM-NEXT:    nop
+; RV32I-FPELIM-EMPTY:
 ; RV32I-FPELIM-NEXT:    #NO_APP
 ; RV32I-FPELIM-NEXT:    lui a0, 97
 ; RV32I-FPELIM-NEXT:    addi a0, a0, 672
@@ -103,10 +105,12 @@ define void @test_emergency_spill_slot(i32 %a) {
 ; RV32I-WITHFP-NEXT:    add a1, a2, a1
 ; RV32I-WITHFP-NEXT:    #APP
 ; RV32I-WITHFP-NEXT:    nop
+; RV32I-WITHFP-EMPTY:
 ; RV32I-WITHFP-NEXT:    #NO_APP
 ; RV32I-WITHFP-NEXT:    sw a0, 0(a1)
 ; RV32I-WITHFP-NEXT:    #APP
 ; RV32I-WITHFP-NEXT:    nop
+; RV32I-WITHFP-EMPTY:
 ; RV32I-WITHFP-NEXT:    #NO_APP
 ; RV32I-WITHFP-NEXT:    lui a0, 97
 ; RV32I-WITHFP-NEXT:    addi a0, a0, 688

From b6912c879ed848fd59c108e8b90fe0180893ee56 Mon Sep 17 00:00:00 2001
From: Qiu Chaofan 
Date: Mon, 13 Jul 2020 12:15:44 +0800
Subject: [PATCH 066/771] [PowerPC] Support constrained conversion in SPE
 target

This patch adds support for constrained int/fp conversion between
signed/unsigned i32 and f32/f64.

Reviewed By: jhibbits

Differential Revision: https://reviews.llvm.org/D82747
---
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp |   8 +-
 llvm/lib/Target/PowerPC/PPCInstrSPE.td      |  16 +-
 llvm/test/CodeGen/PowerPC/fp-strict-conv.ll | 274 ++++++++++++++++++++
 3 files changed, 288 insertions(+), 10 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/fp-strict-conv.ll

diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 49140bab51343..575ad68fecd99 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -423,6 +423,9 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
 
   if (Subtarget.hasSPE()) {
     // SPE has built-in conversions
+    setOperationAction(ISD::STRICT_FP_TO_SINT, MVT::i32, Legal);
+    setOperationAction(ISD::STRICT_SINT_TO_FP, MVT::i32, Legal);
+    setOperationAction(ISD::STRICT_UINT_TO_FP, MVT::i32, Legal);
     setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
     setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
     setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
@@ -572,9 +575,10 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
       setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
   } else {
     // PowerPC does not have FP_TO_UINT on 32-bit implementations.
-    if (Subtarget.hasSPE())
+    if (Subtarget.hasSPE()) {
+      setOperationAction(ISD::STRICT_FP_TO_UINT, MVT::i32, Legal);
       setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
-    else
+    } else
       setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
   }
 
diff --git a/llvm/lib/Target/PowerPC/PPCInstrSPE.td b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
index 935c3044ae470..858eb0c9fe500 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrSPE.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
@@ -158,7 +158,7 @@ def EFDCFSF        : EFXForm_2a<755, (outs sperc:$RT), (ins spe4rc:$RB),
 
 def EFDCFSI        : EFXForm_2a<753, (outs sperc:$RT), (ins gprc:$RB),
                                 "efdcfsi $RT, $RB", IIC_FPDGeneral,
-                                [(set f64:$RT, (sint_to_fp i32:$RB))]>;
+                                [(set f64:$RT, (any_sint_to_fp i32:$RB))]>;
 
 def EFDCFSID       : EFXForm_2a<739, (outs sperc:$RT), (ins gprc:$RB),
                                 "efdcfsid $RT, $RB", IIC_FPDGeneral,
@@ -169,7 +169,7 @@ def EFDCFUF        : EFXForm_2a<754, (outs sperc:$RT), (ins spe4rc:$RB),
 
 def EFDCFUI        : EFXForm_2a<752, (outs sperc:$RT), (ins gprc:$RB),
                                 "efdcfui $RT, $RB", IIC_FPDGeneral,
-                                [(set f64:$RT, (uint_to_fp i32:$RB))]>;
+                                [(set f64:$RT, (any_uint_to_fp i32:$RB))]>;
 
 def EFDCFUID       : EFXForm_2a<738, (outs sperc:$RT), (ins gprc:$RB),
                                 "efdcfuid $RT, $RB", IIC_FPDGeneral,
@@ -197,7 +197,7 @@ def EFDCTSIDZ      : EFXForm_2a<747, (outs gprc:$RT), (ins sperc:$RB),
 
 def EFDCTSIZ       : EFXForm_2a<762, (outs gprc:$RT), (ins sperc:$RB),
                                 "efdctsiz $RT, $RB", IIC_FPDGeneral,
-                                [(set i32:$RT, (fp_to_sint f64:$RB))]>;
+                                [(set i32:$RT, (any_fp_to_sint f64:$RB))]>;
 
 def EFDCTUF        : EFXForm_2a<758, (outs sperc:$RT), (ins spe4rc:$RB),
                                 "efdctuf $RT, $RB", IIC_FPDGeneral, []>;
@@ -212,7 +212,7 @@ def EFDCTUIDZ      : EFXForm_2a<746, (outs gprc:$RT), (ins sperc:$RB),
 
 def EFDCTUIZ       : EFXForm_2a<760, (outs gprc:$RT), (ins sperc:$RB),
                                 "efdctuiz $RT, $RB", IIC_FPDGeneral,
-                                [(set i32:$RT, (fp_to_uint f64:$RB))]>;
+                                [(set i32:$RT, (any_fp_to_uint f64:$RB))]>;
 
 def EFDDIV         : EFXForm_1<745, (outs sperc:$RT), (ins sperc:$RA, sperc:$RB),
                                "efddiv $RT, $RA, $RB", IIC_FPDivD,
@@ -261,14 +261,14 @@ def EFSCFSF        : EFXForm_2a<723, (outs spe4rc:$RT), (ins spe4rc:$RB),
 
 def EFSCFSI        : EFXForm_2a<721, (outs spe4rc:$RT), (ins gprc:$RB),
                                 "efscfsi $RT, $RB", IIC_FPSGeneral,
-                                [(set f32:$RT, (sint_to_fp i32:$RB))]>;
+                                [(set f32:$RT, (any_sint_to_fp i32:$RB))]>;
 
 def EFSCFUF        : EFXForm_2a<722, (outs spe4rc:$RT), (ins spe4rc:$RB),
                                 "efscfuf $RT, $RB", IIC_FPSGeneral, []>;
 
 def EFSCFUI        : EFXForm_2a<720, (outs spe4rc:$RT), (ins gprc:$RB),
                                 "efscfui $RT, $RB", IIC_FPSGeneral,
-                                [(set f32:$RT, (uint_to_fp i32:$RB))]>;
+                                [(set f32:$RT, (any_uint_to_fp i32:$RB))]>;
 
 let isCompare = 1 in {
 def EFSCMPEQ       : EFXForm_3<718, (outs crrc:$crD), (ins spe4rc:$RA, spe4rc:$RB),
@@ -288,7 +288,7 @@ def EFSCTSI        : EFXForm_2a<725, (outs gprc:$RT), (ins spe4rc:$RB),
 
 def EFSCTSIZ       : EFXForm_2a<730, (outs gprc:$RT), (ins spe4rc:$RB),
                                 "efsctsiz $RT, $RB", IIC_FPSGeneral,
-                                [(set i32:$RT, (fp_to_sint f32:$RB))]>;
+                                [(set i32:$RT, (any_fp_to_sint f32:$RB))]>;
 
 def EFSCTUF        : EFXForm_2a<726, (outs sperc:$RT), (ins spe4rc:$RB),
                                 "efsctuf $RT, $RB", IIC_FPSGeneral, []>;
@@ -299,7 +299,7 @@ def EFSCTUI        : EFXForm_2a<724, (outs gprc:$RT), (ins spe4rc:$RB),
 
 def EFSCTUIZ       : EFXForm_2a<728, (outs gprc:$RT), (ins spe4rc:$RB),
                                 "efsctuiz $RT, $RB", IIC_FPSGeneral,
-                                [(set i32:$RT, (fp_to_uint f32:$RB))]>;
+                                [(set i32:$RT, (any_fp_to_uint f32:$RB))]>;
 
 def EFSDIV         : EFXForm_1<713, (outs spe4rc:$RT), (ins spe4rc:$RA, spe4rc:$RB),
                                "efsdiv $RT, $RA, $RB", IIC_FPDivD,
diff --git a/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll b/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll
new file mode 100644
index 0000000000000..ab806a19c158e
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/fp-strict-conv.ll
@@ -0,0 +1,274 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -verify-machineinstrs -ppc-asm-full-reg-names < %s -mcpu=e500 \
+; RUN:   -mtriple=powerpc-unknown-linux-gnu -mattr=spe | FileCheck %s \
+; RUN:   -check-prefix=SPE
+
+declare i32 @llvm.experimental.constrained.fptosi.i32.f64(double, metadata)
+declare i64 @llvm.experimental.constrained.fptosi.i64.f64(double, metadata)
+declare i64 @llvm.experimental.constrained.fptoui.i64.f64(double, metadata)
+declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata)
+
+declare i32 @llvm.experimental.constrained.fptosi.i32.f32(float, metadata)
+declare i64 @llvm.experimental.constrained.fptosi.i64.f32(float, metadata)
+declare i64 @llvm.experimental.constrained.fptoui.i64.f32(float, metadata)
+declare i32 @llvm.experimental.constrained.fptoui.i32.f32(float, metadata)
+
+declare double @llvm.experimental.constrained.sitofp.f64.i32(i32, metadata, metadata)
+declare double @llvm.experimental.constrained.sitofp.f64.i64(i64, metadata, metadata)
+declare double @llvm.experimental.constrained.uitofp.f64.i32(i32, metadata, metadata)
+declare double @llvm.experimental.constrained.uitofp.f64.i64(i64, metadata, metadata)
+
+declare float @llvm.experimental.constrained.sitofp.f32.i64(i64, metadata, metadata)
+declare float @llvm.experimental.constrained.sitofp.f32.i32(i32, metadata, metadata)
+declare float @llvm.experimental.constrained.uitofp.f32.i32(i32, metadata, metadata)
+declare float @llvm.experimental.constrained.uitofp.f32.i64(i64, metadata, metadata)
+
+define i32 @d_to_i32(double %m) #0 {
+; SPE-LABEL: d_to_i32:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    evmergelo r3, r3, r4
+; SPE-NEXT:    efdctsiz r3, r3
+; SPE-NEXT:    blr
+entry:
+  %conv = call i32 @llvm.experimental.constrained.fptosi.i32.f64(double %m, metadata !"fpexcept.strict") #0
+  ret i32 %conv
+}
+
+define i64 @d_to_i64(double %m) #0 {
+; SPE-LABEL: d_to_i64:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    mflr r0
+; SPE-NEXT:    stw r0, 4(r1)
+; SPE-NEXT:    stwu r1, -16(r1)
+; SPE-NEXT:    .cfi_def_cfa_offset 16
+; SPE-NEXT:    .cfi_offset lr, 4
+; SPE-NEXT:    evmergelo r4, r3, r4
+; SPE-NEXT:    evmergehi r3, r4, r4
+; SPE-NEXT:    # kill: def $r4 killed $r4 killed $s4
+; SPE-NEXT:    # kill: def $r3 killed $r3 killed $s3
+; SPE-NEXT:    bl __fixdfdi
+; SPE-NEXT:    lwz r0, 20(r1)
+; SPE-NEXT:    addi r1, r1, 16
+; SPE-NEXT:    mtlr r0
+; SPE-NEXT:    blr
+entry:
+  %conv = call i64 @llvm.experimental.constrained.fptosi.i64.f64(double %m, metadata !"fpexcept.strict") #0
+  ret i64 %conv
+}
+
+define i64 @d_to_u64(double %m) #0 {
+; SPE-LABEL: d_to_u64:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    mflr r0
+; SPE-NEXT:    stw r0, 4(r1)
+; SPE-NEXT:    stwu r1, -16(r1)
+; SPE-NEXT:    .cfi_def_cfa_offset 16
+; SPE-NEXT:    .cfi_offset lr, 4
+; SPE-NEXT:    evmergelo r4, r3, r4
+; SPE-NEXT:    evmergehi r3, r4, r4
+; SPE-NEXT:    # kill: def $r4 killed $r4 killed $s4
+; SPE-NEXT:    # kill: def $r3 killed $r3 killed $s3
+; SPE-NEXT:    bl __fixunsdfdi
+; SPE-NEXT:    lwz r0, 20(r1)
+; SPE-NEXT:    addi r1, r1, 16
+; SPE-NEXT:    mtlr r0
+; SPE-NEXT:    blr
+entry:
+  %conv = call i64 @llvm.experimental.constrained.fptoui.i64.f64(double %m, metadata !"fpexcept.strict") #0
+  ret i64 %conv
+}
+
+define zeroext i32 @d_to_u32(double %m) #0 {
+; SPE-LABEL: d_to_u32:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    evmergelo r3, r3, r4
+; SPE-NEXT:    efdctuiz r3, r3
+; SPE-NEXT:    blr
+entry:
+  %conv = call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %m, metadata !"fpexcept.strict") #0
+  ret i32 %conv
+}
+
+define signext i32 @f_to_i32(float %m) #0 {
+; SPE-LABEL: f_to_i32:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    efsctsiz r3, r3
+; SPE-NEXT:    blr
+entry:
+  %conv = call i32 @llvm.experimental.constrained.fptosi.i32.f32(float %m, metadata !"fpexcept.strict") #0
+  ret i32 %conv
+}
+
+define i64 @f_to_i64(float %m) #0 {
+; SPE-LABEL: f_to_i64:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    mflr r0
+; SPE-NEXT:    stw r0, 4(r1)
+; SPE-NEXT:    stwu r1, -16(r1)
+; SPE-NEXT:    .cfi_def_cfa_offset 16
+; SPE-NEXT:    .cfi_offset lr, 4
+; SPE-NEXT:    bl __fixsfdi
+; SPE-NEXT:    lwz r0, 20(r1)
+; SPE-NEXT:    addi r1, r1, 16
+; SPE-NEXT:    mtlr r0
+; SPE-NEXT:    blr
+entry:
+  %conv = call i64 @llvm.experimental.constrained.fptosi.i64.f32(float %m, metadata !"fpexcept.strict") #0
+  ret i64 %conv
+}
+
+define i64 @f_to_u64(float %m) #0 {
+; SPE-LABEL: f_to_u64:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    mflr r0
+; SPE-NEXT:    stw r0, 4(r1)
+; SPE-NEXT:    stwu r1, -16(r1)
+; SPE-NEXT:    .cfi_def_cfa_offset 16
+; SPE-NEXT:    .cfi_offset lr, 4
+; SPE-NEXT:    bl __fixunssfdi
+; SPE-NEXT:    lwz r0, 20(r1)
+; SPE-NEXT:    addi r1, r1, 16
+; SPE-NEXT:    mtlr r0
+; SPE-NEXT:    blr
+entry:
+  %conv = call i64 @llvm.experimental.constrained.fptoui.i64.f32(float %m, metadata !"fpexcept.strict") #0
+  ret i64 %conv
+}
+
+define zeroext i32 @f_to_u32(float %m) #0 {
+; SPE-LABEL: f_to_u32:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    efsctuiz r3, r3
+; SPE-NEXT:    blr
+entry:
+  %conv = call i32 @llvm.experimental.constrained.fptoui.i32.f32(float %m, metadata !"fpexcept.strict") #0
+  ret i32 %conv
+}
+
+define double @i32_to_d(i32 signext %m) #0 {
+; SPE-LABEL: i32_to_d:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    efdcfsi r4, r3
+; SPE-NEXT:    evmergehi r3, r4, r4
+; SPE-NEXT:    # kill: def $r4 killed $r4 killed $s4
+; SPE-NEXT:    # kill: def $r3 killed $r3 killed $s3
+; SPE-NEXT:    blr
+entry:
+  %conv = tail call double @llvm.experimental.constrained.sitofp.f64.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret double %conv
+}
+
+define double @i64_to_d(i64 %m) #0 {
+; SPE-LABEL: i64_to_d:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    mflr r0
+; SPE-NEXT:    stw r0, 4(r1)
+; SPE-NEXT:    stwu r1, -16(r1)
+; SPE-NEXT:    .cfi_def_cfa_offset 16
+; SPE-NEXT:    .cfi_offset lr, 4
+; SPE-NEXT:    bl __floatdidf
+; SPE-NEXT:    evmergelo r4, r3, r4
+; SPE-NEXT:    evmergehi r3, r4, r4
+; SPE-NEXT:    lwz r0, 20(r1)
+; SPE-NEXT:    # kill: def $r3 killed $r3 killed $s3
+; SPE-NEXT:    # kill: def $r4 killed $r4 killed $s4
+; SPE-NEXT:    addi r1, r1, 16
+; SPE-NEXT:    mtlr r0
+; SPE-NEXT:    blr
+entry:
+  %conv = tail call double @llvm.experimental.constrained.sitofp.f64.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret double %conv
+}
+
+define double @u32_to_d(i32 zeroext %m) #0 {
+; SPE-LABEL: u32_to_d:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    efdcfui r4, r3
+; SPE-NEXT:    evmergehi r3, r4, r4
+; SPE-NEXT:    # kill: def $r4 killed $r4 killed $s4
+; SPE-NEXT:    # kill: def $r3 killed $r3 killed $s3
+; SPE-NEXT:    blr
+entry:
+  %conv = tail call double @llvm.experimental.constrained.uitofp.f64.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret double %conv
+}
+
+define double @u64_to_d(i64 %m) #0 {
+; SPE-LABEL: u64_to_d:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    mflr r0
+; SPE-NEXT:    stw r0, 4(r1)
+; SPE-NEXT:    stwu r1, -16(r1)
+; SPE-NEXT:    .cfi_def_cfa_offset 16
+; SPE-NEXT:    .cfi_offset lr, 4
+; SPE-NEXT:    bl __floatundidf
+; SPE-NEXT:    evmergelo r4, r3, r4
+; SPE-NEXT:    evmergehi r3, r4, r4
+; SPE-NEXT:    lwz r0, 20(r1)
+; SPE-NEXT:    # kill: def $r3 killed $r3 killed $s3
+; SPE-NEXT:    # kill: def $r4 killed $r4 killed $s4
+; SPE-NEXT:    addi r1, r1, 16
+; SPE-NEXT:    mtlr r0
+; SPE-NEXT:    blr
+entry:
+  %conv = tail call double @llvm.experimental.constrained.uitofp.f64.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret double %conv
+}
+
+define float @i32_to_f(i32 signext %m) #0 {
+; SPE-LABEL: i32_to_f:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    efscfsi r3, r3
+; SPE-NEXT:    blr
+entry:
+  %conv = tail call float @llvm.experimental.constrained.sitofp.f32.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret float %conv
+}
+
+define float @i64_to_f(i64 %m) #0 {
+; SPE-LABEL: i64_to_f:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    mflr r0
+; SPE-NEXT:    stw r0, 4(r1)
+; SPE-NEXT:    stwu r1, -16(r1)
+; SPE-NEXT:    .cfi_def_cfa_offset 16
+; SPE-NEXT:    .cfi_offset lr, 4
+; SPE-NEXT:    bl __floatdisf
+; SPE-NEXT:    lwz r0, 20(r1)
+; SPE-NEXT:    addi r1, r1, 16
+; SPE-NEXT:    mtlr r0
+; SPE-NEXT:    blr
+entry:
+  %conv = tail call float @llvm.experimental.constrained.sitofp.f32.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret float %conv
+}
+
+define float @u32_to_f(i32 zeroext %m) #0 {
+; SPE-LABEL: u32_to_f:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    efscfui r3, r3
+; SPE-NEXT:    blr
+entry:
+  %conv = tail call float @llvm.experimental.constrained.uitofp.f32.i32(i32 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret float %conv
+}
+
+define float @u64_to_f(i64 %m) #0 {
+; SPE-LABEL: u64_to_f:
+; SPE:       # %bb.0: # %entry
+; SPE-NEXT:    mflr r0
+; SPE-NEXT:    stw r0, 4(r1)
+; SPE-NEXT:    stwu r1, -16(r1)
+; SPE-NEXT:    .cfi_def_cfa_offset 16
+; SPE-NEXT:    .cfi_offset lr, 4
+; SPE-NEXT:    bl __floatundisf
+; SPE-NEXT:    lwz r0, 20(r1)
+; SPE-NEXT:    addi r1, r1, 16
+; SPE-NEXT:    mtlr r0
+; SPE-NEXT:    blr
+entry:
+  %conv = tail call float @llvm.experimental.constrained.uitofp.f32.i64(i64 %m, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
+  ret float %conv
+}
+
+attributes #0 = { strictfp }

From ac8dc526c4717907bed11b2fc7ab0db5a0f466ba Mon Sep 17 00:00:00 2001
From: Kai Luo 
Date: Mon, 13 Jul 2020 04:31:04 +0000
Subject: [PATCH 067/771] [PowerPC] Enhance tests for D83276. NFC.

---
 .../PowerPC/stack-clash-prologue-nounwind.ll  | 474 ++++++++++++++++++
 .../CodeGen/PowerPC/stack-clash-prologue.ll   |  51 +-
 2 files changed, 510 insertions(+), 15 deletions(-)
 create mode 100644 llvm/test/CodeGen/PowerPC/stack-clash-prologue-nounwind.ll

diff --git a/llvm/test/CodeGen/PowerPC/stack-clash-prologue-nounwind.ll b/llvm/test/CodeGen/PowerPC/stack-clash-prologue-nounwind.ll
new file mode 100644
index 0000000000000..e595d8a732a5c
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/stack-clash-prologue-nounwind.ll
@@ -0,0 +1,474 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -ppc-asm-full-reg-names -verify-machineinstrs \
+; RUN:   -mtriple=powerpc64le-linux-gnu < %s | FileCheck \
+; RUN:   -check-prefix=CHECK-LE %s
+; RUN: llc -ppc-asm-full-reg-names -verify-machineinstrs \
+; RUN:   -mtriple=powerpc64-linux-gnu < %s | FileCheck \
+; RUN:   -check-prefix=CHECK-BE %s
+; RUN: llc -ppc-asm-full-reg-names -verify-machineinstrs \
+; RUN:   -mtriple=powerpc-linux-gnu < %s | FileCheck \
+; RUN:   -check-prefix=CHECK-32 %s
+
+; Free probe
+define i8 @f0() #0 nounwind {
+; CHECK-LE-LABEL: f0:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    li r3, 3
+; CHECK-LE-NEXT:    stb r3, -64(r1)
+; CHECK-LE-NEXT:    lbz r3, -64(r1)
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: f0:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    li r3, 3
+; CHECK-BE-NEXT:    stb r3, -64(r1)
+; CHECK-BE-NEXT:    lbz r3, -64(r1)
+; CHECK-BE-NEXT:    blr
+;
+; CHECK-32-LABEL: f0:
+; CHECK-32:       # %bb.0: # %entry
+; CHECK-32-NEXT:    stwu r1, -80(r1)
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    stb r3, 16(r1)
+; CHECK-32-NEXT:    lbz r3, 16(r1)
+; CHECK-32-NEXT:    addi r1, r1, 80
+; CHECK-32-NEXT:    blr
+entry:
+  %a = alloca i8, i64 64
+  %b = getelementptr inbounds i8, i8* %a, i64 63
+  store volatile i8 3, i8* %a
+  %c = load volatile i8, i8* %a
+  ret i8 %c
+}
+
+define i8 @f1() #0 "stack-probe-size"="0" nounwind {
+; CHECK-LE-LABEL: f1:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    mr r12, r1
+; CHECK-LE-NEXT:    li r0, 259
+; CHECK-LE-NEXT:    mtctr r0
+; CHECK-LE-NEXT:  .LBB1_1: # %entry
+; CHECK-LE-NEXT:    #
+; CHECK-LE-NEXT:    stdu r12, -16(r1)
+; CHECK-LE-NEXT:    bdnz .LBB1_1
+; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    li r3, 3
+; CHECK-LE-NEXT:    stb r3, 48(r1)
+; CHECK-LE-NEXT:    lbz r3, 48(r1)
+; CHECK-LE-NEXT:    addi r1, r1, 4144
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: f1:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    mr r12, r1
+; CHECK-BE-NEXT:    li r0, 260
+; CHECK-BE-NEXT:    mtctr r0
+; CHECK-BE-NEXT:  .LBB1_1: # %entry
+; CHECK-BE-NEXT:    #
+; CHECK-BE-NEXT:    stdu r12, -16(r1)
+; CHECK-BE-NEXT:    bdnz .LBB1_1
+; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    li r3, 3
+; CHECK-BE-NEXT:    stb r3, 64(r1)
+; CHECK-BE-NEXT:    lbz r3, 64(r1)
+; CHECK-BE-NEXT:    addi r1, r1, 4160
+; CHECK-BE-NEXT:    blr
+;
+; CHECK-32-LABEL: f1:
+; CHECK-32:       # %bb.0: # %entry
+; CHECK-32-NEXT:    mr r12, r1
+; CHECK-32-NEXT:    li r0, 257
+; CHECK-32-NEXT:    mtctr r0
+; CHECK-32-NEXT:  .LBB1_1: # %entry
+; CHECK-32-NEXT:    #
+; CHECK-32-NEXT:    stwu r12, -16(r1)
+; CHECK-32-NEXT:    bdnz .LBB1_1
+; CHECK-32-NEXT:  # %bb.2: # %entry
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    sub r0, r1, r12
+; CHECK-32-NEXT:    stb r3, 16(r1)
+; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    lbz r3, 16(r1)
+; CHECK-32-NEXT:    addi r1, r1, 4112
+; CHECK-32-NEXT:    blr
+entry:
+  %a = alloca i8, i64 4096
+  %b = getelementptr inbounds i8, i8* %a, i64 63
+  store volatile i8 3, i8* %a
+  %c = load volatile i8, i8* %a
+  ret i8 %c
+}
+
+define i8 @f2() #0 nounwind {
+; CHECK-LE-LABEL: f2:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    mr r12, r1
+; CHECK-LE-NEXT:    stdu r12, -48(r1)
+; CHECK-LE-NEXT:    li r0, 16
+; CHECK-LE-NEXT:    mtctr r0
+; CHECK-LE-NEXT:  .LBB2_1: # %entry
+; CHECK-LE-NEXT:    #
+; CHECK-LE-NEXT:    stdu r12, -4096(r1)
+; CHECK-LE-NEXT:    bdnz .LBB2_1
+; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    li r3, 3
+; CHECK-LE-NEXT:    stb r3, 48(r1)
+; CHECK-LE-NEXT:    lbz r3, 48(r1)
+; CHECK-LE-NEXT:    ld r1, 0(r1)
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: f2:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    mr r12, r1
+; CHECK-BE-NEXT:    stdu r12, -64(r1)
+; CHECK-BE-NEXT:    li r0, 16
+; CHECK-BE-NEXT:    mtctr r0
+; CHECK-BE-NEXT:  .LBB2_1: # %entry
+; CHECK-BE-NEXT:    #
+; CHECK-BE-NEXT:    stdu r12, -4096(r1)
+; CHECK-BE-NEXT:    bdnz .LBB2_1
+; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    li r3, 3
+; CHECK-BE-NEXT:    stb r3, 64(r1)
+; CHECK-BE-NEXT:    lbz r3, 64(r1)
+; CHECK-BE-NEXT:    ld r1, 0(r1)
+; CHECK-BE-NEXT:    blr
+;
+; CHECK-32-LABEL: f2:
+; CHECK-32:       # %bb.0: # %entry
+; CHECK-32-NEXT:    mr r12, r1
+; CHECK-32-NEXT:    stwu r12, -16(r1)
+; CHECK-32-NEXT:    li r0, 16
+; CHECK-32-NEXT:    mtctr r0
+; CHECK-32-NEXT:  .LBB2_1: # %entry
+; CHECK-32-NEXT:    #
+; CHECK-32-NEXT:    stwu r12, -4096(r1)
+; CHECK-32-NEXT:    bdnz .LBB2_1
+; CHECK-32-NEXT:  # %bb.2: # %entry
+; CHECK-32-NEXT:    sub r0, r1, r12
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    stb r3, 16(r1)
+; CHECK-32-NEXT:    mr r0, r31
+; CHECK-32-NEXT:    lbz r3, 16(r1)
+; CHECK-32-NEXT:    lwz r31, 0(r1)
+; CHECK-32-NEXT:    mr r1, r31
+; CHECK-32-NEXT:    mr r31, r0
+; CHECK-32-NEXT:    blr
+entry:
+  %a = alloca i8, i64 65536
+  %b = getelementptr inbounds i8, i8* %a, i64 63
+  store volatile i8 3, i8* %a
+  %c = load volatile i8, i8* %a
+  ret i8 %c
+}
+
+define i8 @f3() #0 "stack-probe-size"="32768" nounwind {
+; CHECK-LE-LABEL: f3:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    mr r12, r1
+; CHECK-LE-NEXT:    stdu r12, -48(r1)
+; CHECK-LE-NEXT:    stdu r12, -32768(r1)
+; CHECK-LE-NEXT:    stdu r12, -32768(r1)
+; CHECK-LE-NEXT:    li r3, 3
+; CHECK-LE-NEXT:    stb r3, 48(r1)
+; CHECK-LE-NEXT:    lbz r3, 48(r1)
+; CHECK-LE-NEXT:    ld r1, 0(r1)
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: f3:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    mr r12, r1
+; CHECK-BE-NEXT:    stdu r12, -64(r1)
+; CHECK-BE-NEXT:    stdu r12, -32768(r1)
+; CHECK-BE-NEXT:    stdu r12, -32768(r1)
+; CHECK-BE-NEXT:    li r3, 3
+; CHECK-BE-NEXT:    stb r3, 64(r1)
+; CHECK-BE-NEXT:    lbz r3, 64(r1)
+; CHECK-BE-NEXT:    ld r1, 0(r1)
+; CHECK-BE-NEXT:    blr
+;
+; CHECK-32-LABEL: f3:
+; CHECK-32:       # %bb.0: # %entry
+; CHECK-32-NEXT:    mr r12, r1
+; CHECK-32-NEXT:    stwu r12, -16(r1)
+; CHECK-32-NEXT:    stwu r12, -32768(r1)
+; CHECK-32-NEXT:    stwu r12, -32768(r1)
+; CHECK-32-NEXT:    sub r0, r1, r12
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    stb r3, 16(r1)
+; CHECK-32-NEXT:    mr r0, r31
+; CHECK-32-NEXT:    lbz r3, 16(r1)
+; CHECK-32-NEXT:    lwz r31, 0(r1)
+; CHECK-32-NEXT:    mr r1, r31
+; CHECK-32-NEXT:    mr r31, r0
+; CHECK-32-NEXT:    blr
+entry:
+  %a = alloca i8, i64 65536
+  %b = getelementptr inbounds i8, i8* %a, i64 63
+  store volatile i8 3, i8* %a
+  %c = load volatile i8, i8* %a
+  ret i8 %c
+}
+
+; Same as f2, but without protection.
+define i8 @f4() nounwind {
+; CHECK-LE-LABEL: f4:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    lis r0, -2
+; CHECK-LE-NEXT:    ori r0, r0, 65488
+; CHECK-LE-NEXT:    stdux r1, r1, r0
+; CHECK-LE-NEXT:    li r3, 3
+; CHECK-LE-NEXT:    stb r3, 48(r1)
+; CHECK-LE-NEXT:    lbz r3, 48(r1)
+; CHECK-LE-NEXT:    ld r1, 0(r1)
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: f4:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    lis r0, -2
+; CHECK-BE-NEXT:    ori r0, r0, 65472
+; CHECK-BE-NEXT:    stdux r1, r1, r0
+; CHECK-BE-NEXT:    li r3, 3
+; CHECK-BE-NEXT:    stb r3, 64(r1)
+; CHECK-BE-NEXT:    lbz r3, 64(r1)
+; CHECK-BE-NEXT:    ld r1, 0(r1)
+; CHECK-BE-NEXT:    blr
+;
+; CHECK-32-LABEL: f4:
+; CHECK-32:       # %bb.0: # %entry
+; CHECK-32-NEXT:    lis r0, -2
+; CHECK-32-NEXT:    ori r0, r0, 65520
+; CHECK-32-NEXT:    stwux r1, r1, r0
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    stb r3, 16(r1)
+; CHECK-32-NEXT:    mr r0, r31
+; CHECK-32-NEXT:    lbz r3, 16(r1)
+; CHECK-32-NEXT:    lwz r31, 0(r1)
+; CHECK-32-NEXT:    mr r1, r31
+; CHECK-32-NEXT:    mr r31, r0
+; CHECK-32-NEXT:    blr
+entry:
+  %a = alloca i8, i64 65536
+  %b = getelementptr inbounds i8, i8* %a, i64 63
+  store volatile i8 3, i8* %a
+  %c = load volatile i8, i8* %a
+  ret i8 %c
+}
+
+define i8 @f5() #0 "stack-probe-size"="65536" nounwind {
+; CHECK-LE-LABEL: f5:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    mr r12, r1
+; CHECK-LE-NEXT:    stdu r12, -48(r1)
+; CHECK-LE-NEXT:    li r0, 16
+; CHECK-LE-NEXT:    mtctr r0
+; CHECK-LE-NEXT:    lis r0, -1
+; CHECK-LE-NEXT:    nop
+; CHECK-LE-NEXT:  .LBB5_1: # %entry
+; CHECK-LE-NEXT:    #
+; CHECK-LE-NEXT:    stdux r12, r1, r0
+; CHECK-LE-NEXT:    bdnz .LBB5_1
+; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    li r3, 3
+; CHECK-LE-NEXT:    stb r3, 48(r1)
+; CHECK-LE-NEXT:    lbz r3, 48(r1)
+; CHECK-LE-NEXT:    ld r1, 0(r1)
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: f5:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    mr r12, r1
+; CHECK-BE-NEXT:    stdu r12, -64(r1)
+; CHECK-BE-NEXT:    li r0, 16
+; CHECK-BE-NEXT:    mtctr r0
+; CHECK-BE-NEXT:    lis r0, -1
+; CHECK-BE-NEXT:    nop
+; CHECK-BE-NEXT:  .LBB5_1: # %entry
+; CHECK-BE-NEXT:    #
+; CHECK-BE-NEXT:    stdux r12, r1, r0
+; CHECK-BE-NEXT:    bdnz .LBB5_1
+; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    li r3, 3
+; CHECK-BE-NEXT:    stb r3, 64(r1)
+; CHECK-BE-NEXT:    lbz r3, 64(r1)
+; CHECK-BE-NEXT:    ld r1, 0(r1)
+; CHECK-BE-NEXT:    blr
+;
+; CHECK-32-LABEL: f5:
+; CHECK-32:       # %bb.0: # %entry
+; CHECK-32-NEXT:    mr r12, r1
+; CHECK-32-NEXT:    stwu r12, -16(r1)
+; CHECK-32-NEXT:    li r0, 16
+; CHECK-32-NEXT:    mtctr r0
+; CHECK-32-NEXT:    lis r0, -1
+; CHECK-32-NEXT:    nop
+; CHECK-32-NEXT:  .LBB5_1: # %entry
+; CHECK-32-NEXT:    #
+; CHECK-32-NEXT:    stwux r12, r1, r0
+; CHECK-32-NEXT:    bdnz .LBB5_1
+; CHECK-32-NEXT:  # %bb.2: # %entry
+; CHECK-32-NEXT:    sub r0, r1, r12
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    stb r3, 16(r1)
+; CHECK-32-NEXT:    mr r0, r31
+; CHECK-32-NEXT:    lbz r3, 16(r1)
+; CHECK-32-NEXT:    lwz r31, 0(r1)
+; CHECK-32-NEXT:    mr r1, r31
+; CHECK-32-NEXT:    mr r31, r0
+; CHECK-32-NEXT:    blr
+entry:
+  %a = alloca i8, i64 1048576
+  %b = getelementptr inbounds i8, i8* %a, i64 63
+  store volatile i8 3, i8* %a
+  %c = load volatile i8, i8* %a
+  ret i8 %c
+}
+
+define i8 @f6() #0 nounwind {
+; CHECK-LE-LABEL: f6:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    mr r12, r1
+; CHECK-LE-NEXT:    stdu r12, -48(r1)
+; CHECK-LE-NEXT:    lis r0, 4
+; CHECK-LE-NEXT:    nop
+; CHECK-LE-NEXT:    mtctr r0
+; CHECK-LE-NEXT:  .LBB6_1: # %entry
+; CHECK-LE-NEXT:    #
+; CHECK-LE-NEXT:    stdu r12, -4096(r1)
+; CHECK-LE-NEXT:    bdnz .LBB6_1
+; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    li r3, 3
+; CHECK-LE-NEXT:    stb r3, 48(r1)
+; CHECK-LE-NEXT:    lbz r3, 48(r1)
+; CHECK-LE-NEXT:    ld r1, 0(r1)
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: f6:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    mr r12, r1
+; CHECK-BE-NEXT:    stdu r12, -64(r1)
+; CHECK-BE-NEXT:    lis r0, 4
+; CHECK-BE-NEXT:    nop
+; CHECK-BE-NEXT:    mtctr r0
+; CHECK-BE-NEXT:  .LBB6_1: # %entry
+; CHECK-BE-NEXT:    #
+; CHECK-BE-NEXT:    stdu r12, -4096(r1)
+; CHECK-BE-NEXT:    bdnz .LBB6_1
+; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    li r3, 3
+; CHECK-BE-NEXT:    stb r3, 64(r1)
+; CHECK-BE-NEXT:    lbz r3, 64(r1)
+; CHECK-BE-NEXT:    ld r1, 0(r1)
+; CHECK-BE-NEXT:    blr
+;
+; CHECK-32-LABEL: f6:
+; CHECK-32:       # %bb.0: # %entry
+; CHECK-32-NEXT:    mr r12, r1
+; CHECK-32-NEXT:    stwu r12, -16(r1)
+; CHECK-32-NEXT:    lis r0, 4
+; CHECK-32-NEXT:    nop
+; CHECK-32-NEXT:    mtctr r0
+; CHECK-32-NEXT:  .LBB6_1: # %entry
+; CHECK-32-NEXT:    #
+; CHECK-32-NEXT:    stwu r12, -4096(r1)
+; CHECK-32-NEXT:    bdnz .LBB6_1
+; CHECK-32-NEXT:  # %bb.2: # %entry
+; CHECK-32-NEXT:    sub r0, r1, r12
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    stb r3, 16(r1)
+; CHECK-32-NEXT:    mr r0, r31
+; CHECK-32-NEXT:    lbz r3, 16(r1)
+; CHECK-32-NEXT:    lwz r31, 0(r1)
+; CHECK-32-NEXT:    mr r1, r31
+; CHECK-32-NEXT:    mr r31, r0
+; CHECK-32-NEXT:    blr
+entry:
+  %a = alloca i8, i64 1073741824
+  %b = getelementptr inbounds i8, i8* %a, i64 63
+  store volatile i8 3, i8* %a
+  %c = load volatile i8, i8* %a
+  ret i8 %c
+}
+
+define i8 @f7() #0 "stack-probe-size"="65536" nounwind {
+; CHECK-LE-LABEL: f7:
+; CHECK-LE:       # %bb.0: # %entry
+; CHECK-LE-NEXT:    lis r0, -1
+; CHECK-LE-NEXT:    mr r12, r1
+; CHECK-LE-NEXT:    ori r0, r0, 13776
+; CHECK-LE-NEXT:    stdux r12, r1, r0
+; CHECK-LE-NEXT:    li r0, 15258
+; CHECK-LE-NEXT:    mtctr r0
+; CHECK-LE-NEXT:    lis r0, -1
+; CHECK-LE-NEXT:    nop
+; CHECK-LE-NEXT:  .LBB7_1: # %entry
+; CHECK-LE-NEXT:    #
+; CHECK-LE-NEXT:    stdux r12, r1, r0
+; CHECK-LE-NEXT:    bdnz .LBB7_1
+; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    li r3, 3
+; CHECK-LE-NEXT:    stb r3, 41(r1)
+; CHECK-LE-NEXT:    lbz r3, 41(r1)
+; CHECK-LE-NEXT:    ld r1, 0(r1)
+; CHECK-LE-NEXT:    blr
+;
+; CHECK-BE-LABEL: f7:
+; CHECK-BE:       # %bb.0: # %entry
+; CHECK-BE-NEXT:    lis r0, -1
+; CHECK-BE-NEXT:    mr r12, r1
+; CHECK-BE-NEXT:    ori r0, r0, 13760
+; CHECK-BE-NEXT:    stdux r12, r1, r0
+; CHECK-BE-NEXT:    li r0, 15258
+; CHECK-BE-NEXT:    mtctr r0
+; CHECK-BE-NEXT:    lis r0, -1
+; CHECK-BE-NEXT:    nop
+; CHECK-BE-NEXT:  .LBB7_1: # %entry
+; CHECK-BE-NEXT:    #
+; CHECK-BE-NEXT:    stdux r12, r1, r0
+; CHECK-BE-NEXT:    bdnz .LBB7_1
+; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    li r3, 3
+; CHECK-BE-NEXT:    stb r3, 57(r1)
+; CHECK-BE-NEXT:    lbz r3, 57(r1)
+; CHECK-BE-NEXT:    ld r1, 0(r1)
+; CHECK-BE-NEXT:    blr
+;
+; CHECK-32-LABEL: f7:
+; CHECK-32:       # %bb.0: # %entry
+; CHECK-32-NEXT:    lis r0, -1
+; CHECK-32-NEXT:    mr r12, r1
+; CHECK-32-NEXT:    ori r0, r0, 13808
+; CHECK-32-NEXT:    stwux r12, r1, r0
+; CHECK-32-NEXT:    li r0, 15258
+; CHECK-32-NEXT:    mtctr r0
+; CHECK-32-NEXT:    lis r0, -1
+; CHECK-32-NEXT:    nop
+; CHECK-32-NEXT:  .LBB7_1: # %entry
+; CHECK-32-NEXT:    #
+; CHECK-32-NEXT:    stwux r12, r1, r0
+; CHECK-32-NEXT:    bdnz .LBB7_1
+; CHECK-32-NEXT:  # %bb.2: # %entry
+; CHECK-32-NEXT:    sub r0, r1, r12
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    stb r3, 9(r1)
+; CHECK-32-NEXT:    mr r0, r31
+; CHECK-32-NEXT:    lbz r3, 9(r1)
+; CHECK-32-NEXT:    lwz r31, 0(r1)
+; CHECK-32-NEXT:    mr r1, r31
+; CHECK-32-NEXT:    mr r31, r0
+; CHECK-32-NEXT:    blr
+entry:
+  %a = alloca i8, i64 1000000007
+  %b = getelementptr inbounds i8, i8* %a, i64 101
+  store volatile i8 3, i8* %a
+  %c = load volatile i8, i8* %a
+  ret i8 %c
+}
+
+attributes #0 = { "probe-stack"="inline-asm" }
diff --git a/llvm/test/CodeGen/PowerPC/stack-clash-prologue.ll b/llvm/test/CodeGen/PowerPC/stack-clash-prologue.ll
index e595d8a732a5c..eb8e05eef519f 100644
--- a/llvm/test/CodeGen/PowerPC/stack-clash-prologue.ll
+++ b/llvm/test/CodeGen/PowerPC/stack-clash-prologue.ll
@@ -41,7 +41,7 @@ entry:
   ret i8 %c
 }
 
-define i8 @f1() #0 "stack-probe-size"="0" nounwind {
+define i8 @f1() #0 "stack-probe-size"="0" {
 ; CHECK-LE-LABEL: f1:
 ; CHECK-LE:       # %bb.0: # %entry
 ; CHECK-LE-NEXT:    mr r12, r1
@@ -52,6 +52,7 @@ define i8 @f1() #0 "stack-probe-size"="0" nounwind {
 ; CHECK-LE-NEXT:    stdu r12, -16(r1)
 ; CHECK-LE-NEXT:    bdnz .LBB1_1
 ; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    .cfi_def_cfa_offset 4144
 ; CHECK-LE-NEXT:    li r3, 3
 ; CHECK-LE-NEXT:    stb r3, 48(r1)
 ; CHECK-LE-NEXT:    lbz r3, 48(r1)
@@ -68,6 +69,7 @@ define i8 @f1() #0 "stack-probe-size"="0" nounwind {
 ; CHECK-BE-NEXT:    stdu r12, -16(r1)
 ; CHECK-BE-NEXT:    bdnz .LBB1_1
 ; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    .cfi_def_cfa_offset 4160
 ; CHECK-BE-NEXT:    li r3, 3
 ; CHECK-BE-NEXT:    stb r3, 64(r1)
 ; CHECK-BE-NEXT:    lbz r3, 64(r1)
@@ -84,10 +86,11 @@ define i8 @f1() #0 "stack-probe-size"="0" nounwind {
 ; CHECK-32-NEXT:    stwu r12, -16(r1)
 ; CHECK-32-NEXT:    bdnz .LBB1_1
 ; CHECK-32-NEXT:  # %bb.2: # %entry
-; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    sub r0, r1, r12
-; CHECK-32-NEXT:    stb r3, 16(r1)
 ; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    .cfi_def_cfa_offset 4112
+; CHECK-32-NEXT:    li r3, 3
+; CHECK-32-NEXT:    stb r3, 16(r1)
 ; CHECK-32-NEXT:    lbz r3, 16(r1)
 ; CHECK-32-NEXT:    addi r1, r1, 4112
 ; CHECK-32-NEXT:    blr
@@ -99,7 +102,7 @@ entry:
   ret i8 %c
 }
 
-define i8 @f2() #0 nounwind {
+define i8 @f2() #0 {
 ; CHECK-LE-LABEL: f2:
 ; CHECK-LE:       # %bb.0: # %entry
 ; CHECK-LE-NEXT:    mr r12, r1
@@ -111,6 +114,7 @@ define i8 @f2() #0 nounwind {
 ; CHECK-LE-NEXT:    stdu r12, -4096(r1)
 ; CHECK-LE-NEXT:    bdnz .LBB2_1
 ; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    .cfi_def_cfa_offset 65584
 ; CHECK-LE-NEXT:    li r3, 3
 ; CHECK-LE-NEXT:    stb r3, 48(r1)
 ; CHECK-LE-NEXT:    lbz r3, 48(r1)
@@ -128,6 +132,7 @@ define i8 @f2() #0 nounwind {
 ; CHECK-BE-NEXT:    stdu r12, -4096(r1)
 ; CHECK-BE-NEXT:    bdnz .LBB2_1
 ; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    .cfi_def_cfa_offset 65600
 ; CHECK-BE-NEXT:    li r3, 3
 ; CHECK-BE-NEXT:    stb r3, 64(r1)
 ; CHECK-BE-NEXT:    lbz r3, 64(r1)
@@ -146,8 +151,9 @@ define i8 @f2() #0 nounwind {
 ; CHECK-32-NEXT:    bdnz .LBB2_1
 ; CHECK-32-NEXT:  # %bb.2: # %entry
 ; CHECK-32-NEXT:    sub r0, r1, r12
-; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    .cfi_def_cfa_offset 65552
+; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    stb r3, 16(r1)
 ; CHECK-32-NEXT:    mr r0, r31
 ; CHECK-32-NEXT:    lbz r3, 16(r1)
@@ -163,13 +169,14 @@ entry:
   ret i8 %c
 }
 
-define i8 @f3() #0 "stack-probe-size"="32768" nounwind {
+define i8 @f3() #0 "stack-probe-size"="32768" {
 ; CHECK-LE-LABEL: f3:
 ; CHECK-LE:       # %bb.0: # %entry
 ; CHECK-LE-NEXT:    mr r12, r1
 ; CHECK-LE-NEXT:    stdu r12, -48(r1)
 ; CHECK-LE-NEXT:    stdu r12, -32768(r1)
 ; CHECK-LE-NEXT:    stdu r12, -32768(r1)
+; CHECK-LE-NEXT:    .cfi_def_cfa_offset 65584
 ; CHECK-LE-NEXT:    li r3, 3
 ; CHECK-LE-NEXT:    stb r3, 48(r1)
 ; CHECK-LE-NEXT:    lbz r3, 48(r1)
@@ -182,6 +189,7 @@ define i8 @f3() #0 "stack-probe-size"="32768" nounwind {
 ; CHECK-BE-NEXT:    stdu r12, -64(r1)
 ; CHECK-BE-NEXT:    stdu r12, -32768(r1)
 ; CHECK-BE-NEXT:    stdu r12, -32768(r1)
+; CHECK-BE-NEXT:    .cfi_def_cfa_offset 65600
 ; CHECK-BE-NEXT:    li r3, 3
 ; CHECK-BE-NEXT:    stb r3, 64(r1)
 ; CHECK-BE-NEXT:    lbz r3, 64(r1)
@@ -195,8 +203,9 @@ define i8 @f3() #0 "stack-probe-size"="32768" nounwind {
 ; CHECK-32-NEXT:    stwu r12, -32768(r1)
 ; CHECK-32-NEXT:    stwu r12, -32768(r1)
 ; CHECK-32-NEXT:    sub r0, r1, r12
-; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    .cfi_def_cfa_offset 65552
+; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    stb r3, 16(r1)
 ; CHECK-32-NEXT:    mr r0, r31
 ; CHECK-32-NEXT:    lbz r3, 16(r1)
@@ -213,12 +222,13 @@ entry:
 }
 
 ; Same as f2, but without protection.
-define i8 @f4() nounwind {
+define i8 @f4() {
 ; CHECK-LE-LABEL: f4:
 ; CHECK-LE:       # %bb.0: # %entry
 ; CHECK-LE-NEXT:    lis r0, -2
 ; CHECK-LE-NEXT:    ori r0, r0, 65488
 ; CHECK-LE-NEXT:    stdux r1, r1, r0
+; CHECK-LE-NEXT:    .cfi_def_cfa_offset 65584
 ; CHECK-LE-NEXT:    li r3, 3
 ; CHECK-LE-NEXT:    stb r3, 48(r1)
 ; CHECK-LE-NEXT:    lbz r3, 48(r1)
@@ -230,6 +240,7 @@ define i8 @f4() nounwind {
 ; CHECK-BE-NEXT:    lis r0, -2
 ; CHECK-BE-NEXT:    ori r0, r0, 65472
 ; CHECK-BE-NEXT:    stdux r1, r1, r0
+; CHECK-BE-NEXT:    .cfi_def_cfa_offset 65600
 ; CHECK-BE-NEXT:    li r3, 3
 ; CHECK-BE-NEXT:    stb r3, 64(r1)
 ; CHECK-BE-NEXT:    lbz r3, 64(r1)
@@ -241,8 +252,9 @@ define i8 @f4() nounwind {
 ; CHECK-32-NEXT:    lis r0, -2
 ; CHECK-32-NEXT:    ori r0, r0, 65520
 ; CHECK-32-NEXT:    stwux r1, r1, r0
-; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    .cfi_def_cfa_offset 65552
+; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    stb r3, 16(r1)
 ; CHECK-32-NEXT:    mr r0, r31
 ; CHECK-32-NEXT:    lbz r3, 16(r1)
@@ -258,7 +270,7 @@ entry:
   ret i8 %c
 }
 
-define i8 @f5() #0 "stack-probe-size"="65536" nounwind {
+define i8 @f5() #0 "stack-probe-size"="65536" {
 ; CHECK-LE-LABEL: f5:
 ; CHECK-LE:       # %bb.0: # %entry
 ; CHECK-LE-NEXT:    mr r12, r1
@@ -272,6 +284,7 @@ define i8 @f5() #0 "stack-probe-size"="65536" nounwind {
 ; CHECK-LE-NEXT:    stdux r12, r1, r0
 ; CHECK-LE-NEXT:    bdnz .LBB5_1
 ; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    .cfi_def_cfa_offset 1048624
 ; CHECK-LE-NEXT:    li r3, 3
 ; CHECK-LE-NEXT:    stb r3, 48(r1)
 ; CHECK-LE-NEXT:    lbz r3, 48(r1)
@@ -291,6 +304,7 @@ define i8 @f5() #0 "stack-probe-size"="65536" nounwind {
 ; CHECK-BE-NEXT:    stdux r12, r1, r0
 ; CHECK-BE-NEXT:    bdnz .LBB5_1
 ; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    .cfi_def_cfa_offset 1048640
 ; CHECK-BE-NEXT:    li r3, 3
 ; CHECK-BE-NEXT:    stb r3, 64(r1)
 ; CHECK-BE-NEXT:    lbz r3, 64(r1)
@@ -311,8 +325,9 @@ define i8 @f5() #0 "stack-probe-size"="65536" nounwind {
 ; CHECK-32-NEXT:    bdnz .LBB5_1
 ; CHECK-32-NEXT:  # %bb.2: # %entry
 ; CHECK-32-NEXT:    sub r0, r1, r12
-; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    .cfi_def_cfa_offset 1048592
+; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    stb r3, 16(r1)
 ; CHECK-32-NEXT:    mr r0, r31
 ; CHECK-32-NEXT:    lbz r3, 16(r1)
@@ -328,7 +343,7 @@ entry:
   ret i8 %c
 }
 
-define i8 @f6() #0 nounwind {
+define i8 @f6() #0 {
 ; CHECK-LE-LABEL: f6:
 ; CHECK-LE:       # %bb.0: # %entry
 ; CHECK-LE-NEXT:    mr r12, r1
@@ -341,6 +356,7 @@ define i8 @f6() #0 nounwind {
 ; CHECK-LE-NEXT:    stdu r12, -4096(r1)
 ; CHECK-LE-NEXT:    bdnz .LBB6_1
 ; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    .cfi_def_cfa_offset 1073741872
 ; CHECK-LE-NEXT:    li r3, 3
 ; CHECK-LE-NEXT:    stb r3, 48(r1)
 ; CHECK-LE-NEXT:    lbz r3, 48(r1)
@@ -359,6 +375,7 @@ define i8 @f6() #0 nounwind {
 ; CHECK-BE-NEXT:    stdu r12, -4096(r1)
 ; CHECK-BE-NEXT:    bdnz .LBB6_1
 ; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    .cfi_def_cfa_offset 1073741888
 ; CHECK-BE-NEXT:    li r3, 3
 ; CHECK-BE-NEXT:    stb r3, 64(r1)
 ; CHECK-BE-NEXT:    lbz r3, 64(r1)
@@ -378,8 +395,9 @@ define i8 @f6() #0 nounwind {
 ; CHECK-32-NEXT:    bdnz .LBB6_1
 ; CHECK-32-NEXT:  # %bb.2: # %entry
 ; CHECK-32-NEXT:    sub r0, r1, r12
-; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    .cfi_def_cfa_offset 1073741840
+; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    stb r3, 16(r1)
 ; CHECK-32-NEXT:    mr r0, r31
 ; CHECK-32-NEXT:    lbz r3, 16(r1)
@@ -395,7 +413,7 @@ entry:
   ret i8 %c
 }
 
-define i8 @f7() #0 "stack-probe-size"="65536" nounwind {
+define i8 @f7() #0 "stack-probe-size"="65536" {
 ; CHECK-LE-LABEL: f7:
 ; CHECK-LE:       # %bb.0: # %entry
 ; CHECK-LE-NEXT:    lis r0, -1
@@ -411,6 +429,7 @@ define i8 @f7() #0 "stack-probe-size"="65536" nounwind {
 ; CHECK-LE-NEXT:    stdux r12, r1, r0
 ; CHECK-LE-NEXT:    bdnz .LBB7_1
 ; CHECK-LE-NEXT:  # %bb.2: # %entry
+; CHECK-LE-NEXT:    .cfi_def_cfa_offset 1000000048
 ; CHECK-LE-NEXT:    li r3, 3
 ; CHECK-LE-NEXT:    stb r3, 41(r1)
 ; CHECK-LE-NEXT:    lbz r3, 41(r1)
@@ -432,6 +451,7 @@ define i8 @f7() #0 "stack-probe-size"="65536" nounwind {
 ; CHECK-BE-NEXT:    stdux r12, r1, r0
 ; CHECK-BE-NEXT:    bdnz .LBB7_1
 ; CHECK-BE-NEXT:  # %bb.2: # %entry
+; CHECK-BE-NEXT:    .cfi_def_cfa_offset 1000000064
 ; CHECK-BE-NEXT:    li r3, 3
 ; CHECK-BE-NEXT:    stb r3, 57(r1)
 ; CHECK-BE-NEXT:    lbz r3, 57(r1)
@@ -454,8 +474,9 @@ define i8 @f7() #0 "stack-probe-size"="65536" nounwind {
 ; CHECK-32-NEXT:    bdnz .LBB7_1
 ; CHECK-32-NEXT:  # %bb.2: # %entry
 ; CHECK-32-NEXT:    sub r0, r1, r12
-; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    sub r0, r1, r0
+; CHECK-32-NEXT:    .cfi_def_cfa_offset 1000000016
+; CHECK-32-NEXT:    li r3, 3
 ; CHECK-32-NEXT:    stb r3, 9(r1)
 ; CHECK-32-NEXT:    mr r0, r31
 ; CHECK-32-NEXT:    lbz r3, 9(r1)

From e808cab824488af137b62902e65dec3827b83b46 Mon Sep 17 00:00:00 2001
From: Max Kazantsev 
Date: Mon, 13 Jul 2020 11:14:59 +0700
Subject: [PATCH 068/771] [InstCombine] Improve select -> phi canonicalization:
 consider more blocks

We can try to replace select with a Phi not in its parent block alone,
but also in blocks of its arguments. We benefit from it when select's
argument is a Phi.

Differential Revision: https://reviews.llvm.org/D83284
Reviewed By: nikic
---
 .../InstCombine/InstCombineSelect.cpp         |  21 ++-
 llvm/test/Transforms/InstCombine/select.ll    | 169 +++++++++++++++++-
 2 files changed, 184 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 233fb3878ba72..17124f717af79 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2443,11 +2443,11 @@ Instruction *InstCombiner::foldVectorSelect(SelectInst &Sel) {
   return nullptr;
 }
 
-static Instruction *foldSelectToPhi(SelectInst &Sel, const DominatorTree &DT,
-                                    InstCombiner::BuilderTy &Builder) {
+static Instruction *foldSelectToPhiImpl(SelectInst &Sel, BasicBlock *BB,
+                                        const DominatorTree &DT,
+                                        InstCombiner::BuilderTy &Builder) {
   // Find the block's immediate dominator that ends with a conditional branch
   // that matches select's condition (maybe inverted).
-  BasicBlock *BB = Sel.getParent();
   auto *IDomNode = DT[BB]->getIDom();
   if (!IDomNode)
     return nullptr;
@@ -2500,6 +2500,21 @@ static Instruction *foldSelectToPhi(SelectInst &Sel, const DominatorTree &DT,
   return PN;
 }
 
+static Instruction *foldSelectToPhi(SelectInst &Sel, const DominatorTree &DT,
+                                    InstCombiner::BuilderTy &Builder) {
+  // Try to replace this select with Phi in one of these blocks.
+  SmallSetVector CandidateBlocks;
+  CandidateBlocks.insert(Sel.getParent());
+  for (Value *V : Sel.operands())
+    if (auto *I = dyn_cast(V))
+      CandidateBlocks.insert(I->getParent());
+
+  for (BasicBlock *BB : CandidateBlocks)
+    if (auto *PN = foldSelectToPhiImpl(Sel, BB, DT, Builder))
+      return PN;
+  return nullptr;
+}
+
 Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
   Value *CondVal = SI.getCondition();
   Value *TrueVal = SI.getTrueValue();
diff --git a/llvm/test/Transforms/InstCombine/select.ll b/llvm/test/Transforms/InstCombine/select.ll
index f990a58f984ce..08e547a6ea0ad 100644
--- a/llvm/test/Transforms/InstCombine/select.ll
+++ b/llvm/test/Transforms/InstCombine/select.ll
@@ -2250,11 +2250,40 @@ define i32 @test_select_into_phi_not_idom(i1 %cond, i32 %A, i32 %B)  {
 ; CHECK:       if.false:
 ; CHECK-NEXT:    br label [[MERGE]]
 ; CHECK:       merge:
-; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ [[A:%.*]], [[IF_TRUE]] ], [ [[B:%.*]], [[IF_FALSE]] ]
 ; CHECK-NEXT:    br label [[EXIT:%.*]]
 ; CHECK:       exit:
-; CHECK-NEXT:    [[SEL:%.*]] = select i1 [[COND]], i32 [[PHI]], i32 [[A]]
-; CHECK-NEXT:    ret i32 [[SEL]]
+; CHECK-NEXT:    ret i32 [[A:%.*]]
+;
+entry:
+  br i1 %cond, label %if.true, label %if.false
+
+if.true:
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  %phi = phi i32 [%A, %if.true], [%B, %if.false]
+  br label %exit
+
+exit:
+  %sel = select i1 %cond, i32 %phi, i32 %A
+  ret i32 %sel
+}
+
+define i32 @test_select_into_phi_not_idom_2(i1 %cond, i32 %A, i32 %B)  {
+; CHECK-LABEL: @test_select_into_phi_not_idom_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i32 [[B:%.*]]
 ;
 entry:
   br i1 %cond, label %if.true, label %if.false
@@ -2269,11 +2298,145 @@ merge:
   %phi = phi i32 [%A, %if.true], [%B, %if.false]
   br label %exit
 
+exit:
+  %sel = select i1 %cond, i32 %B, i32 %phi
+  ret i32 %sel
+}
+
+define i32 @test_select_into_phi_not_idom_inverted(i1 %cond, i32 %A, i32 %B)  {
+; CHECK-LABEL: @test_select_into_phi_not_idom_inverted(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_FALSE:%.*]], label [[IF_TRUE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[SEL:%.*]] = phi i32 [ [[B:%.*]], [[IF_FALSE]] ], [ [[A:%.*]], [[IF_TRUE]] ]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+entry:
+  %inverted = xor i1 %cond, 1
+  br i1 %inverted, label %if.true, label %if.false
+
+if.true:
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  %phi = phi i32 [%A, %if.true], [%B, %if.false]
+  br label %exit
+
+exit:
+  %sel = select i1 %cond, i32 %phi, i32 %A
+  ret i32 %sel
+}
+
+define i32 @test_select_into_phi_not_idom_inverted_2(i1 %cond, i32 %A, i32 %B)  {
+; CHECK-LABEL: @test_select_into_phi_not_idom_inverted_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_FALSE:%.*]], label [[IF_TRUE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[SEL:%.*]] = phi i32 [ [[B:%.*]], [[IF_FALSE]] ], [ [[A:%.*]], [[IF_TRUE]] ]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+entry:
+  %inverted = xor i1 %cond, 1
+  br i1 %inverted, label %if.true, label %if.false
+
+if.true:
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  %phi = phi i32 [%A, %if.true], [%B, %if.false]
+  br label %exit
+
+exit:
+  %sel = select i1 %cond, i32 %B, i32 %phi
+  ret i32 %sel
+}
+
+define i32 @test_select_into_phi_not_idom_no_dom_input_1(i1 %cond, i32 %A, i32 %B, i32 *%p)  {
+; CHECK-LABEL: @test_select_into_phi_not_idom_no_dom_input_1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    [[C:%.*]] = load i32, i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[SEL:%.*]] = phi i32 [ [[A:%.*]], [[IF_FALSE]] ], [ [[C]], [[IF_TRUE]] ]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+entry:
+  br i1 %cond, label %if.true, label %if.false
+
+if.true:
+  %C = load i32, i32* %p
+  br label %merge
+
+if.false:
+  br label %merge
+
+merge:
+  %phi = phi i32 [%C, %if.true], [%B, %if.false]
+  br label %exit
+
 exit:
   %sel = select i1 %cond, i32 %phi, i32 %A
   ret i32 %sel
 }
 
+define i32 @test_select_into_phi_not_idom_no_dom_input_2(i1 %cond, i32 %A, i32 %B, i32 *%p)  {
+; CHECK-LABEL: @test_select_into_phi_not_idom_no_dom_input_2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
+; CHECK:       if.true:
+; CHECK-NEXT:    br label [[MERGE:%.*]]
+; CHECK:       if.false:
+; CHECK-NEXT:    [[C:%.*]] = load i32, i32* [[P:%.*]], align 4
+; CHECK-NEXT:    br label [[MERGE]]
+; CHECK:       merge:
+; CHECK-NEXT:    [[SEL:%.*]] = phi i32 [ [[C]], [[IF_FALSE]] ], [ [[B:%.*]], [[IF_TRUE]] ]
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret i32 [[SEL]]
+;
+entry:
+  br i1 %cond, label %if.true, label %if.false
+
+if.true:
+  br label %merge
+
+if.false:
+  %C = load i32, i32* %p
+  br label %merge
+
+merge:
+  %phi = phi i32 [%A, %if.true], [%C, %if.false]
+  br label %exit
+
+exit:
+  %sel = select i1 %cond, i32 %B, i32 %phi
+  ret i32 %sel
+}
+
 ; Negative tests to ensure we don't remove selects with undef true/false values.
 ; See https://bugs.llvm.org/show_bug.cgi?id=31633
 ; https://lists.llvm.org/pipermail/llvm-dev/2016-October/106182.html

From 07c4c7e7959b7fd09830bbdf4dcd533e98aa45ab Mon Sep 17 00:00:00 2001
From: Aleksandr Platonov 
Date: Mon, 13 Jul 2020 09:04:29 +0200
Subject: [PATCH 069/771] [clangd] Fix tests build for GCC5
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Summary:
Build log:
```
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp: In member function ‘virtual void clang::clangd::{anonymous}::PreamblePatchTest_Define_Test::TestBody()’:
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:267:3: error: could not convert ‘(const char*)"\012        #define BAR\012        [[BAR]]"’ from ‘const char*’ to ‘llvm::StringLitera ’
   };
   ^
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:267:3: error: could not convert ‘(const char*)"#line 0 \".*main.cpp\"\012#line 2\012#define         BAR\012"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:267:3: error: could not convert ‘(const char*)"\012        #define BAR \\\012\012        [[BAR]]"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:267:3: error: could not convert ‘(const char*)"#line 0 \".*main.cpp\"\012#line 2\012#define         BAR\012"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:267:3: error: could not convert ‘(const char*)"\012        #define \\\012                BAR\012        [[BAR]]"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:267:3: error: could not convert ‘(const char*)"#line 0 \".*main.cpp\"\012#line 3\012#define         BAR\012"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp: In member function ‘virtual void clang::clangd::{anonymous}::PreamblePatchTest_LocateMacroAtWorks_Test::TestBody()’:
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)""’ from ‘const char*’ to ‘llvm::StringLiteral’
   };
   ^
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)"\012            #define $def^FOO\012            $use^FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)""’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)"\012            #define $def^FOO\012            #undef $use^FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)""’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)"\012            #define $def^FOO\012            #undef FOO\012            $use^FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)""’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)"\012            #define \\\012              $def^FOO\012            $use^FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)""’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)"\012            #\\\012              define /* FOO */\\\012              /* FOO */ $def^FOO\012            $use^FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)"#define FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:357:3: error: could not convert ‘(const char*)"\012            #define BAR\012            #define $def^FOO\012            $use^FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp: In member function ‘virtual void clang::clangd::{anonymous}::PreamblePatchTest_RefsToMacros_Test::TestBody()’:
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:445:3: error: could not convert ‘(const char*)""’ from ‘const char*’ to ‘llvm::StringLiteral’
   };
   ^
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:445:3: error: could not convert ‘(const char*)"\012            #define ^FOO\012            ^[[FOO]]"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:445:3: error: could not convert ‘(const char*)"#define FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:445:3: error: could not convert ‘(const char*)"\012            #define BAR\012            #define ^FOO\012            ^[[FOO]]"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:445:3: error: could not convert ‘(const char*)""’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:445:3: error: could not convert ‘(const char*)"\012            #define ^FOO\012            #undef ^FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp: In member function ‘virtual void clang::clangd::{anonymous}::PreamblePatch_ModifiedBounds_Test::TestBody()’:
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:512:3: error: could not convert ‘(const char*)""’ from ‘const char*’ to ‘llvm::StringLiteral’
   };
   ^
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:512:3: error: could not convert ‘(const char*)"\012            #define FOO\012            FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:512:3: error: could not convert ‘(const char*)"#define FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:512:3: error: could not convert ‘(const char*)"#define BAR"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:512:3: error: could not convert ‘(const char*)"\012            #define FOO\012            #undef FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
llvm-project/clang-tools-extra/clangd/unittests/PreambleTests.cpp:512:3: error: could not convert ‘(const char*)"#define FOO"’ from ‘const char*’ to ‘llvm::StringLiteral’
```

Patch by @ArcsinX !

Reviewers: kadircet, sammccall

Reviewed By: kadircet

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D83548
---
 .../clangd/unittests/PreambleTests.cpp         | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/PreambleTests.cpp b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
index 8c9669a945dd7..8482a1cc8237c 100644
--- a/clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -230,8 +230,8 @@ std::string getPreamblePatch(llvm::StringRef Baseline,
 TEST(PreamblePatchTest, Define) {
   // BAR should be defined while parsing the AST.
   struct {
-    llvm::StringLiteral Contents;
-    llvm::StringLiteral ExpectedPatch;
+    const char *const Contents;
+    const char *const ExpectedPatch;
   } Cases[] = {
       {
           R"cpp(
@@ -270,7 +270,7 @@ TEST(PreamblePatchTest, Define) {
     SCOPED_TRACE(Case.Contents);
     Annotations Modified(Case.Contents);
     EXPECT_THAT(getPreamblePatch("", Modified.code()),
-                MatchesRegex(Case.ExpectedPatch.str()));
+                MatchesRegex(Case.ExpectedPatch));
 
     auto AST = createPatchedAST("", Modified.code());
     ASSERT_TRUE(AST);
@@ -304,8 +304,8 @@ TEST(PreamblePatchTest, OrderingPreserved) {
 
 TEST(PreamblePatchTest, LocateMacroAtWorks) {
   struct {
-    llvm::StringLiteral Baseline;
-    llvm::StringLiteral Modified;
+    const char *const Baseline;
+    const char *const Modified;
   } Cases[] = {
       // Addition of new directive
       {
@@ -417,8 +417,8 @@ TEST(PreamblePatchTest, LocateMacroAtDeletion) {
 
 TEST(PreamblePatchTest, RefsToMacros) {
   struct {
-    llvm::StringLiteral Baseline;
-    llvm::StringLiteral Modified;
+    const char *const Baseline;
+    const char *const Modified;
   } Cases[] = {
       // Newly added
       {
@@ -491,8 +491,8 @@ TEST(TranslatePreamblePatchLocation, Simple) {
 
 TEST(PreamblePatch, ModifiedBounds) {
   struct {
-    llvm::StringLiteral Baseline;
-    llvm::StringLiteral Modified;
+    const char *const Baseline;
+    const char *const Modified;
   } Cases[] = {
       // Size increased
       {

From 9df6afbb5c99c103ef27614a8987934ef82f110f Mon Sep 17 00:00:00 2001
From: Frederik Gossen 
Date: Mon, 13 Jul 2020 08:28:13 +0000
Subject: [PATCH 070/771] [MLIR][Shape] Lower `shape.any`

Lower `shape.any` to its first operand.

Differential Revision: https://reviews.llvm.org/D83123
---
 .../ShapeToStandard/ShapeToStandard.cpp       | 17 ++++++++++++++
 .../ShapeToStandardPatterns.td                |  1 -
 .../ShapeToStandard/shape-to-standard.mlir    | 23 +++++++++++++++++++
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.cpp b/mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.cpp
index 7ebcb397349d4..f82019989e705 100644
--- a/mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.cpp
+++ b/mlir/lib/Conversion/ShapeToStandard/ShapeToStandard.cpp
@@ -23,6 +23,22 @@ namespace {
 #include "ShapeToStandardPatterns.inc"
 
 /// Conversion patterns.
+class AnyOpConversion : public OpConversionPattern {
+public:
+  using OpConversionPattern::OpConversionPattern;
+
+  LogicalResult
+  matchAndRewrite(AnyOp op, ArrayRef operands,
+                  ConversionPatternRewriter &rewriter) const override {
+    AnyOp::Adaptor transformed(operands);
+
+    // Replace `any` with its first operand.
+    // Any operand would be a valid substitution.
+    rewriter.replaceOp(op, {transformed.inputs().front()});
+    return success();
+  }
+};
+
 template 
 class BinaryOpConversion : public OpConversionPattern {
 public:
@@ -181,6 +197,7 @@ void mlir::populateShapeToStandardConversionPatterns(
   populateWithGenerated(ctx, &patterns);
   // clang-format off
   patterns.insert<
+      AnyOpConversion,
       BinaryOpConversion,
       BinaryOpConversion,
       ConstSizeOpConverter,
diff --git a/mlir/lib/Conversion/ShapeToStandard/ShapeToStandardPatterns.td b/mlir/lib/Conversion/ShapeToStandard/ShapeToStandardPatterns.td
index a1335487f5ab3..30bed6d7fb65e 100644
--- a/mlir/lib/Conversion/ShapeToStandard/ShapeToStandardPatterns.td
+++ b/mlir/lib/Conversion/ShapeToStandard/ShapeToStandardPatterns.td
@@ -18,4 +18,3 @@ def IndexToSizeOpConversion : Pat<
 def SizeToIndexOpConversion : Pat<
     (Shape_SizeToIndexOp $arg),
     (replaceWithValue $arg)>;
-
diff --git a/mlir/test/Conversion/ShapeToStandard/shape-to-standard.mlir b/mlir/test/Conversion/ShapeToStandard/shape-to-standard.mlir
index 28ef190d09eba..22206637adbf4 100644
--- a/mlir/test/Conversion/ShapeToStandard/shape-to-standard.mlir
+++ b/mlir/test/Conversion/ShapeToStandard/shape-to-standard.mlir
@@ -158,3 +158,26 @@ func @get_extent_from_extent_tensor(%extents : tensor,
   return %result : !shape.size
 }
 
+// -----
+
+// Lower `any` to its first operand.
+// CHECK-LABEL: @any_of_three
+// CHECK-SAME:  (%[[A:.*]]: tensor, %[[B:.*]]: tensor, %[[C:.*]]: tensor) -> tensor
+func @any_of_three(%a : !shape.shape, %b : !shape.shape, %c : !shape.shape)
+    -> !shape.shape {
+  // CHECK: return %[[A]] : tensor
+  %result = shape.any %a, %b, %c
+  return %result : !shape.shape
+}
+
+// -----
+
+// Lower `any` to its first operand.
+// CHECK-LABEL: @any_of_one
+// CHECK-SAME:  (%[[A:.*]]: tensor) -> tensor
+func @any_of_one(%a : !shape.shape) -> !shape.shape {
+  // CHECK: return %[[A]] : tensor
+  %result = shape.any %a
+  return %result : !shape.shape
+}
+

From fd85b40aee4aa4cfcecaf2bfaf86e1de4c78ab0c Mon Sep 17 00:00:00 2001
From: Petar Avramovic 
Date: Mon, 13 Jul 2020 10:52:33 +0200
Subject: [PATCH 071/771] [GlobalISel][InlineAsm] Fix buildCopy for inputs

Check that input size matches size of destination reg class.
Attempt to extend input size when needed.

Differential Revision: https://reviews.llvm.org/D83384
---
 .../CodeGen/GlobalISel/InlineAsmLowering.cpp  | 39 ++++++++++++++++++-
 .../GlobalISel/irtranslator-inline-asm.ll     | 32 +++++++++++++++
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
index 241d5bace248b..2ce1d414e7550 100644
--- a/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/InlineAsmLowering.cpp
@@ -237,6 +237,39 @@ static unsigned getNumOpRegs(const MachineInstr &I, unsigned OpIdx) {
   return InlineAsm::getNumOperandRegisters(Flag);
 }
 
+static bool buildAnyextOrCopy(Register Dst, Register Src,
+                              MachineIRBuilder &MIRBuilder) {
+  const TargetRegisterInfo *TRI =
+      MIRBuilder.getMF().getSubtarget().getRegisterInfo();
+  MachineRegisterInfo *MRI = MIRBuilder.getMRI();
+
+  auto SrcTy = MRI->getType(Src);
+  if (!SrcTy.isValid()) {
+    LLVM_DEBUG(dbgs() << "Source type for copy is not valid\n");
+    return false;
+  }
+  unsigned SrcSize = TRI->getRegSizeInBits(Src, *MRI);
+  unsigned DstSize = TRI->getRegSizeInBits(Dst, *MRI);
+
+  if (DstSize < SrcSize) {
+    LLVM_DEBUG(dbgs() << "Input can't fit in destination reg class\n");
+    return false;
+  }
+
+  // Attempt to anyext small scalar sources.
+  if (DstSize > SrcSize) {
+    if (!SrcTy.isScalar()) {
+      LLVM_DEBUG(dbgs() << "Can't extend non-scalar input to size of"
+                           "destination register class\n");
+      return false;
+    }
+    Src = MIRBuilder.buildAnyExt(LLT::scalar(DstSize), Src).getReg(0);
+  }
+
+  MIRBuilder.buildCopy(Dst, Src);
+  return true;
+}
+
 bool InlineAsmLowering::lowerInlineAsm(
     MachineIRBuilder &MIRBuilder, const CallBase &Call,
     std::function(const Value &Val)> GetOrCreateVRegs)
@@ -427,7 +460,8 @@ bool InlineAsmLowering::lowerInlineAsm(
         ArrayRef SrcRegs = GetOrCreateVRegs(*OpInfo.CallOperandVal);
         assert(SrcRegs.size() == 1 && "Single register is expected here");
         Register Tmp = MRI->createVirtualRegister(RC);
-        MIRBuilder.buildCopy(Tmp, SrcRegs[0]);
+        if (!buildAnyextOrCopy(Tmp, SrcRegs[0], MIRBuilder))
+          return false;
 
         // Add Flag and input register operand (Tmp) to Inst. Tie Tmp to Def.
         unsigned UseFlag = InlineAsm::getFlagWord(InlineAsm::Kind_RegUse, 1);
@@ -525,7 +559,8 @@ bool InlineAsmLowering::lowerInlineAsm(
 
       unsigned Flag = InlineAsm::getFlagWord(InlineAsm::Kind_RegUse, NumRegs);
       Inst.addImm(Flag);
-      MIRBuilder.buildCopy(OpInfo.Regs[0], SourceRegs[0]);
+      if (!buildAnyextOrCopy(OpInfo.Regs[0], SourceRegs[0], MIRBuilder))
+        return false;
       Inst.addReg(OpInfo.Regs[0]);
       break;
     }
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll
index f1be1011fa865..f8b23ef84721e 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-inline-asm.ll
@@ -211,3 +211,35 @@ define i32 @test_memory_constraint(i32* %a) nounwind {
   %1 = tail call i32 asm "ldr $0, $1", "=r,*m"(i32* %a)
   ret i32 %1
 }
+
+define i16 @test_anyext_input() {
+  ; CHECK-LABEL: name: test_anyext_input
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
+  ; CHECK:   [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16)
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32)
+  ; CHECK:   INLINEASM &"", 1 /* sideeffect attdialect */, 655370 /* regdef:GPR32common */, def %0, 9 /* reguse */, [[COPY]]
+  ; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY %0
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
+  ; CHECK:   [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16)
+  ; CHECK:   $w0 = COPY [[ANYEXT1]](s32)
+  ; CHECK:   RET_ReallyLR implicit $w0
+  %1 = call i16 asm sideeffect "", "=r,r"(i16 1)
+  ret i16 %1
+}
+
+define i16 @test_anyext_input_with_matching_constraint() {
+  ; CHECK-LABEL: name: test_anyext_input_with_matching_constraint
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 1
+  ; CHECK:   [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[C]](s16)
+  ; CHECK:   [[COPY:%[0-9]+]]:gpr32common = COPY [[ANYEXT]](s32)
+  ; CHECK:   INLINEASM &"", 1 /* sideeffect attdialect */, 655370 /* regdef:GPR32common */, def %0, 2147483657 /* reguse tiedto:$0 */, [[COPY]](tied-def 3)
+  ; CHECK:   [[COPY1:%[0-9]+]]:_(s32) = COPY %0
+  ; CHECK:   [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32)
+  ; CHECK:   [[ANYEXT1:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC]](s16)
+  ; CHECK:   $w0 = COPY [[ANYEXT1]](s32)
+  ; CHECK:   RET_ReallyLR implicit $w0
+  %1 = call i16 asm sideeffect "", "=r,0"(i16 1)
+  ret i16 %1
+}

From e124062bf3874e1ce7ddad407b35e95ec3d3ac13 Mon Sep 17 00:00:00 2001
From: Ella Ma 
Date: Mon, 13 Jul 2020 12:22:16 +0300
Subject: [PATCH 072/771] Fix bad doxygen result for class
 clang::ento::CallEvent and its derived classes

Summary: Fix bug https://bugs.llvm.org/show_bug.cgi?id=44753. This
patch is a workaround of a Doxygen bug, so that it can correctly
generate documents for class clang::ento::CallEvent and its derived
classes.

Differential Revision: https://reviews.llvm.org/D82356
---
 .../include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
index d75f9f63286db..a2a98c558a4b7 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
@@ -554,7 +554,7 @@ class SimpleFunctionCall : public AnyFunctionCall {
 
 /// Represents a call to a block.
 ///
-/// Example: ^{ /* ... */ }()
+/// Example: ^{ statement-body }()
 class BlockCall : public CallEvent {
   friend class CallEventManager;
 

From 26cf6c1513f95082cedd4f2acf0881dd9ab56461 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Mon, 13 Jul 2020 11:26:45 +0200
Subject: [PATCH 073/771] [clangd] Add metrics for recovery-expr type
 propagation.

Differential Revision: https://reviews.llvm.org/D83657
---
 clang-tools-extra/clangd/Selection.cpp                | 5 ++++-
 clang-tools-extra/clangd/unittests/SelectionTests.cpp | 2 ++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp
index 1db15ba6699a8..e94a3ca5a0c38 100644
--- a/clang-tools-extra/clangd/Selection.cpp
+++ b/clang-tools-extra/clangd/Selection.cpp
@@ -41,10 +41,13 @@ using ast_type_traits::DynTypedNode;
 void recordMetrics(const SelectionTree &S) {
   static constexpr trace::Metric SelectionUsedRecovery(
       "selection_recovery", trace::Metric::Distribution);
+  static constexpr trace::Metric RecoveryType("selection_recovery_type",
+                                              trace::Metric::Distribution);
   const auto *Common = S.commonAncestor();
   for (const auto *N = Common; N; N = N->Parent) {
-    if (N->ASTNode.get()) {
+    if (const auto *RE = N->ASTNode.get()) {
       SelectionUsedRecovery.record(1); // used recovery ast.
+      RecoveryType.record(RE->isTypeDependent() ? 0 : 1);
       return;
     }
   }
diff --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
index 6f8c10e966a88..051580ba6e49b 100644
--- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -453,6 +453,8 @@ TEST(SelectionTree, Metrics) {
   auto T = makeSelectionTree(Code, AST);
   EXPECT_THAT(Tracer.takeMetric("selection_recovery"),
               testing::ElementsAreArray({1}));
+  EXPECT_THAT(Tracer.takeMetric("selection_recovery_type"),
+              testing::ElementsAreArray({1}));
 }
 
 // FIXME: Doesn't select the binary operator node in

From 6ac9e589f869b6a63c9966e7c7ec7cc8207cf2f2 Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Thu, 9 Jul 2020 12:55:46 +0200
Subject: [PATCH 074/771] [clang][RecoveryExpr] Clarify the dependence-bits
 documentation.

The expr dependent-bits described that the expression somehow
depends on a template paramter.

With RecoveryExpr, we have generalized it to "the expression depends on
a template parameter, or an error".  This patch updates/cleanups all related
comments of dependence-bits.

Differential Revision: https://reviews.llvm.org/D83213
---
 clang/include/clang/AST/DependenceFlags.h | 31 +++++++++----
 clang/include/clang/AST/Expr.h            | 56 +++++++++++++++--------
 clang/lib/AST/ComputeDependence.cpp       | 13 ++++--
 clang/lib/Sema/SemaExpr.cpp               |  3 --
 4 files changed, 68 insertions(+), 35 deletions(-)

diff --git a/clang/include/clang/AST/DependenceFlags.h b/clang/include/clang/AST/DependenceFlags.h
index 3601cb90bb765..14a7ffaecb2b0 100644
--- a/clang/include/clang/AST/DependenceFlags.h
+++ b/clang/include/clang/AST/DependenceFlags.h
@@ -16,8 +16,18 @@ namespace clang {
 struct ExprDependenceScope {
   enum ExprDependence : uint8_t {
     UnexpandedPack = 1,
+    // This expr depends in any way on
+    //   - a template parameter, it implies that the resolution of this expr may
+    //     cause instantiation to fail
+    //   - or an error (often in a non-template context)
+    //
+    // Note that C++ standard doesn't define the instantiation-dependent term,
+    // we follow the formal definition coming from the Itanium C++ ABI, and
+    // extend it to errors.
     Instantiation = 2,
+    // The type of this expr depends on a template parameter, or an error.
     Type = 4,
+    // The value of this expr depends on a template parameter, or an error.
     Value = 8,
 
     // clang extension: this expr contains or references an error, and is
@@ -42,10 +52,14 @@ struct TypeDependenceScope {
     /// Whether this type contains an unexpanded parameter pack
     /// (for C++11 variadic templates)
     UnexpandedPack = 1,
-    /// Whether this type somehow involves a template parameter, even
-    /// if the resolution of the type does not depend on a template parameter.
+    /// Whether this type somehow involves
+    ///   - a template parameter, even if the resolution of the type does not
+    ///     depend on a template parameter.
+    ///   - or an error.
     Instantiation = 2,
-    /// Whether this type is a dependent type (C++ [temp.dep.type]).
+    /// Whether this type
+    ///   - is a dependent type (C++ [temp.dep.type])
+    ///   - or it somehow involves an error, e.g. decltype(recovery-expr)
     Dependent = 4,
     /// Whether this type is a variably-modified type (C99 6.7.5).
     VariablyModified = 8,
@@ -95,16 +109,17 @@ class Dependence {
 
     // Contains a template parameter pack that wasn't expanded.
     UnexpandedPack = 1,
-    // Uses a template parameter, even if it doesn't affect the result.
-    // Validity depends on the template parameter.
+    // Depends on a template parameter or an error in some way.
+    // Validity depends on how the template is instantiated or the error is
+    // resolved.
     Instantiation = 2,
-    // Expression type depends on template context.
+    // Expression type depends on template context, or an error.
     // Value and Instantiation should also be set.
     Type = 4,
-    // Expression value depends on template context.
+    // Expression value depends on template context, or an error.
     // Instantiation should also be set.
     Value = 8,
-    // Depends on template context.
+    // Depends on template context, or an error.
     // The type/value distinction is only meaningful for expressions.
     Dependent = Type | Value,
     // Includes an error, and depends on how it is resolved.
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 66eafaaab715e..c13b971192850 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -157,9 +157,11 @@ class Expr : public ValueStmt {
     return static_cast(ExprBits.Dependent);
   }
 
-  /// isValueDependent - Determines whether this expression is
-  /// value-dependent (C++ [temp.dep.constexpr]). For example, the
-  /// array bound of "Chars" in the following example is
+  /// Determines whether the value of this expression depends on
+  ///   - a template parameter (C++ [temp.dep.constexpr])
+  ///   - or an error, whose resolution is unknown
+  ///
+  /// For example, the array bound of "Chars" in the following example is
   /// value-dependent.
   /// @code
   /// template struct meta_string;
@@ -168,10 +170,12 @@ class Expr : public ValueStmt {
     return static_cast(getDependence() & ExprDependence::Value);
   }
 
-  /// isTypeDependent - Determines whether this expression is
-  /// type-dependent (C++ [temp.dep.expr]), which means that its type
-  /// could change from one template instantiation to the next. For
-  /// example, the expressions "x" and "x + y" are type-dependent in
+  /// Determines whether the type of this expression depends on
+  ///   - a template paramter (C++ [temp.dep.expr], which means that its type
+  ///     could change from one template instantiation to the next)
+  ///   - or an error
+  ///
+  /// For example, the expressions "x" and "x + y" are type-dependent in
   /// the following code, but "y" is not type-dependent:
   /// @code
   /// template
@@ -184,8 +188,10 @@ class Expr : public ValueStmt {
   }
 
   /// Whether this expression is instantiation-dependent, meaning that
-  /// it depends in some way on a template parameter, even if neither its type
-  /// nor (constant) value can change due to the template instantiation.
+  /// it depends in some way on
+  ///    - a template parameter (even if neither its type nor (constant) value
+  ///      can change due to the template instantiation)
+  ///    - or an error
   ///
   /// In the following example, the expression \c sizeof(sizeof(T() + T())) is
   /// instantiation-dependent (since it involves a template parameter \c T), but
@@ -200,6 +206,12 @@ class Expr : public ValueStmt {
   /// }
   /// \endcode
   ///
+  /// \code
+  /// void func(int) {
+  ///   func(); // the expression is instantiation-dependent, because it depends
+  ///           // on an error.
+  /// }
+  /// \endcode
   bool isInstantiationDependent() const {
     return static_cast(getDependence() & ExprDependence::Instantiation);
   }
@@ -6212,19 +6224,25 @@ class TypoExpr : public Expr {
 /// subexpressions of some expression that we could not construct and source
 /// range covered by the expression.
 ///
-/// By default, RecoveryExpr is type-, value- and instantiation-dependent to
-/// take advantage of existing machinery to deal with dependent code in C++,
-/// e.g. RecoveryExpr is preserved in `decltype()` as part of the
-/// `DependentDecltypeType`. In addition to that, clang does not report most
-/// errors on dependent expressions, so we get rid of bogus errors for free.
-/// However, note that unlike other dependent expressions, RecoveryExpr can be
-/// produced in non-template contexts.
-/// In addition, we will preserve the type in RecoveryExpr when the type is
-/// known, e.g. preserving the return type for a broken non-overloaded function
-/// call, a overloaded call where all candidates have the same return type.
+/// By default, RecoveryExpr uses dependence-bits to take advantage of existing
+/// machinery to deal with dependent code in C++, e.g. RecoveryExpr is preserved
+/// in `decltype()` as part of the `DependentDecltypeType`. In
+/// addition to that, clang does not report most errors on dependent
+/// expressions, so we get rid of bogus errors for free. However, note that
+/// unlike other dependent expressions, RecoveryExpr can be produced in
+/// non-template contexts.
+///
+/// We will preserve the type in RecoveryExpr when the type is known, e.g.
+/// preserving the return type for a broken non-overloaded function call, a
+/// overloaded call where all candidates have the same return type. In this
+/// case, the expression is not type-dependent (unless the known type is itself
+/// dependent)
 ///
 /// One can also reliably suppress all bogus errors on expressions containing
 /// recovery expressions by examining results of Expr::containsErrors().
+///
+/// FIXME: RecoveryExpr is currently generated by default in C++ mode only, as
+/// dependence isn't handled properly on several C-only codepaths.
 class RecoveryExpr final : public Expr,
                            private llvm::TrailingObjects {
 public:
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index 53c43b194b38c..2333993dbeb40 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -495,13 +495,16 @@ ExprDependence clang::computeDependence(DeclRefExpr *E, const ASTContext &Ctx) {
 }
 
 ExprDependence clang::computeDependence(RecoveryExpr *E) {
-  // Mark the expression as value- and instantiation- dependent to reuse
-  // existing suppressions for dependent code, e.g. avoiding
-  // constant-evaluation.
-  // FIXME: drop type+value+instantiation once Error is sufficient to suppress
-  // bogus dianostics.
+  // RecoveryExpr is
+  //   - always value-dependent, and therefore instantiation dependent
+  //   - contains errors (ExprDependence::Error), by definition
+  //   - type-dependent if we don't know the type (fallback to an opaque
+  //     dependent type), or the type is known and dependent, or it has
+  //     type-dependent subexpressions.
   auto D = toExprDependence(E->getType()->getDependence()) |
            ExprDependence::ValueInstantiation | ExprDependence::Error;
+  // FIXME: remove the type-dependent bit from subexpressions, if the
+  // RecoveryExpr has a non-dependent type.
   for (auto *S : E->subExpressions())
     D |= S->getDependence();
   return D;
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 24b9c6777be17..ccae79636f323 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19180,9 +19180,6 @@ ExprResult Sema::ActOnObjCAvailabilityCheckExpr(
 
 ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End,
                                     ArrayRef SubExprs, QualType T) {
-  // FIXME: enable it for C++, RecoveryExpr is type-dependent to suppress
-  // bogus diagnostics and this trick does not work in C.
-  // FIXME: use containsErrors() to suppress unwanted diags in C.
   if (!Context.getLangOpts().RecoveryAST)
     return ExprError();
 

From afcc9a81d2dce92f98732ecc90433141c346971a Mon Sep 17 00:00:00 2001
From: Kerry McLaughlin 
Date: Mon, 13 Jul 2020 10:08:40 +0100
Subject: [PATCH 075/771] [SVE][Codegen] Add a helper function for pointer
 increment logic

Summary:
Helper used when splitting load & store operations to calculate
the pointer + offset for the high half of the split

Reviewers: efriedma, sdesmalen, david-arm

Reviewed By: efriedma

Subscribers: tschuett, hiraditya, psnobl, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D83577
---
 llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h |  5 ++
 .../SelectionDAG/LegalizeVectorTypes.cpp      | 46 +++++++++----------
 2 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 4bc75ceb4928e..0fa6d653a8364 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -776,6 +776,11 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
   void GetSplitVector(SDValue Op, SDValue &Lo, SDValue &Hi);
   void SetSplitVector(SDValue Op, SDValue Lo, SDValue Hi);
 
+  // Helper function for incrementing the pointer when splitting
+  // memory operations
+  void IncrementPointer(MemSDNode *N, EVT MemVT,
+                        MachinePointerInfo &MPI, SDValue &Ptr);
+
   // Vector Result Splitting: <128 x ty> -> 2 x <64 x ty>.
   void SplitVectorResult(SDNode *N, unsigned ResNo);
   void SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
index 550174f0df72a..414ba25ffd5ff 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
@@ -976,6 +976,25 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
     SetSplitVector(SDValue(N, ResNo), Lo, Hi);
 }
 
+void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
+                                        MachinePointerInfo &MPI,
+                                        SDValue &Ptr) {
+  SDLoc DL(N);
+  unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinSize() / 8;
+
+  if (MemVT.isScalableVector()) {
+    SDValue BytesIncrement = DAG.getVScale(
+        DL, Ptr.getValueType(),
+        APInt(Ptr.getValueSizeInBits().getFixedSize(), IncrementSize));
+    MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
+    Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement);
+  } else {
+    MPI = N->getPointerInfo().getWithOffset(IncrementSize);
+    // Increment the pointer to the other half.
+    Ptr = DAG.getObjectPtrOffset(DL, Ptr, IncrementSize);
+  }
+}
+
 void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo,
                                          SDValue &Hi) {
   SDValue LHSLo, LHSHi;
@@ -1537,19 +1556,8 @@ void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
                    LD->getPointerInfo(), LoMemVT, LD->getOriginalAlign(),
                    MMOFlags, AAInfo);
 
-  unsigned IncrementSize = LoMemVT.getSizeInBits().getKnownMinSize() / 8;
-
   MachinePointerInfo MPI;
-  if (LoVT.isScalableVector()) {
-    SDValue BytesIncrement = DAG.getVScale(
-        dl, Ptr.getValueType(),
-        APInt(Ptr.getValueSizeInBits().getFixedSize(), IncrementSize));
-    MPI = MachinePointerInfo(LD->getPointerInfo().getAddrSpace());
-    Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, BytesIncrement);
-  } else {
-    MPI = LD->getPointerInfo().getWithOffset(IncrementSize);
-    Ptr = DAG.getObjectPtrOffset(dl, Ptr, IncrementSize);
-  }
+  IncrementPointer(LD, LoMemVT, MPI, Ptr);
 
   Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
                    HiMemVT, LD->getOriginalAlign(), MMOFlags, AAInfo);
@@ -2489,8 +2497,6 @@ SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
   if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
     return TLI.scalarizeVectorStore(N, DAG);
 
-  unsigned IncrementSize = LoMemVT.getSizeInBits().getKnownMinSize() / 8;
-
   if (isTruncating)
     Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
                            Alignment, MMOFlags, AAInfo);
@@ -2499,17 +2505,7 @@ SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
                       AAInfo);
 
   MachinePointerInfo MPI;
-  if (LoMemVT.isScalableVector()) {
-    SDValue BytesIncrement = DAG.getVScale(
-        DL, Ptr.getValueType(),
-        APInt(Ptr.getValueSizeInBits().getFixedSize(), IncrementSize));
-    MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
-    Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement);
-  } else {
-    MPI = N->getPointerInfo().getWithOffset(IncrementSize);
-    // Increment the pointer to the other half.
-    Ptr = DAG.getObjectPtrOffset(DL, Ptr, IncrementSize);
-  }
+  IncrementPointer(N, LoMemVT, MPI, Ptr);
 
   if (isTruncating)
     Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,

From 1d3d9c7b589e6471edc0d8a2272c399d2ce6a13c Mon Sep 17 00:00:00 2001
From: Haojian Wu 
Date: Mon, 13 Jul 2020 12:05:09 +0200
Subject: [PATCH 076/771] [clang] Include type specifiers in typo correction
 when checking isCXXDeclarationSpecifiers.

- add more tests (the test added in https://github.com/llvm/llvm-project/commit/2f448467e4254ddc3191136c968e6054bc009b88 is weak);
- improve the `MyTemplate();` case, with this patch, typo correction
  suggests the type decl, and no regressions found.

Differential Revision: https://reviews.llvm.org/D83025
---
 clang/lib/Parse/ParseTentative.cpp      |  5 ++--
 clang/test/Parser/cxx-template-decl.cpp | 14 ----------
 clang/test/SemaCXX/typo-correction.cpp  | 35 +++++++++++++++++++++++++
 3 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 948162c11b3ff..f026f3a1bfb29 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1110,8 +1110,9 @@ class TentativeParseCCC final : public CorrectionCandidateCallback {
 public:
   TentativeParseCCC(const Token &Next) {
     WantRemainingKeywords = false;
-    WantTypeSpecifiers = Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater,
-                                      tok::l_brace, tok::identifier);
+    WantTypeSpecifiers =
+        Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater, tok::l_brace,
+                     tok::identifier, tok::comma);
   }
 
   bool ValidateCandidate(const TypoCorrection &Candidate) override {
diff --git a/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp
index 24cc13cde91fa..64e7ca921f575 100644
--- a/clang/test/Parser/cxx-template-decl.cpp
+++ b/clang/test/Parser/cxx-template-decl.cpp
@@ -286,17 +286,3 @@ namespace PR45239 {
   template int b;
   template auto f() -> b<0>; // expected-error +{{}}
 }
-
-namespace NoCrashOnNullNNSTypoCorrection {
-
-int AddObservation(); // expected-note {{declared here}}
-
-template  // expected-note {{template parameter is declared here}}
-class UsingImpl {};
-class AddObservation {
-  using Using =
-    UsingImpl; // expected-error {{use of undeclared identifier 'AddObservationFn'; did you mean}} \
-                                               expected-error {{template argument for template type parameter must be a type}}
-};
-
-}
diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp
index 92a145074e728..e0325b3ba09bf 100644
--- a/clang/test/SemaCXX/typo-correction.cpp
+++ b/clang/test/SemaCXX/typo-correction.cpp
@@ -611,6 +611,41 @@ int bar() {
 }
 }
 
+namespace testIncludeTypeInTemplateArgument {
+template 
+void foo(T t = {}, U = {}); // expected-note {{candidate template ignored}}
+
+class AddObservation {}; // expected-note {{declared here}}
+int bar1() {
+  // should resolve to a class.
+  foo(); // expected-error {{unknown type name 'AddObservationFn'; did you mean 'AddObservation'?}}
+
+  // should not resolve to a class.
+  foo(AddObservationFn, 1);    // expected-error-re {{use of undeclared identifier 'AddObservationFn'{{$}}}}
+  int a = AddObservationFn, b; // expected-error-re {{use of undeclared identifier 'AddObservationFn'{{$}}}}
+
+  int AddObservation; // expected-note 3{{declared here}}
+  // should resolve to a local variable.
+  foo(AddObservationFn, 1);    // expected-error {{use of undeclared identifier 'AddObservationFn'; did you mean}}
+  int c = AddObservationFn, d; // expected-error {{use of undeclared identifier 'AddObservationFn'; did you mean}}
+
+  // FIXME: would be nice to not resolve to a variable.
+  foo(); // expected-error {{use of undeclared identifier 'AddObservationFn'; did you mean}} \
+                                   expected-error {{no matching function for call}}
+}
+} // namespace testIncludeTypeInTemplateArgument
+
+namespace testNoCrashOnNullNNSTypoCorrection {
+int AddObservation();
+template 
+class UsingImpl {};
+class AddObservation { // expected-note {{declared here}}
+  using Using =
+      // should resolve to a class.
+      UsingImpl; // expected-error {{unknown type name 'AddObservationFn'; did you mean}}
+};
+} // namespace testNoCrashOnNullNNSTypoCorrection
+
 namespace testNonStaticMemberHandling {
 struct Foo {
   bool usesMetadata;  // expected-note {{'usesMetadata' declared here}}

From ce23e54162edcb0de9b7af1f457229da0bbfe79d Mon Sep 17 00:00:00 2001
From: Mirko Brkusanin 
Date: Mon, 13 Jul 2020 11:44:18 +0200
Subject: [PATCH 077/771] [AMDGPU][GlobalISel] Select llvm.amdgcn.ballot

Select ballot intrinsic for GlobalISel.

Differential Revision: https://reviews.llvm.org/D83214
---
 .../AMDGPU/AMDGPUInstructionSelector.cpp      | 36 +++++++++
 .../Target/AMDGPU/AMDGPUInstructionSelector.h |  1 +
 .../Target/AMDGPU/AMDGPURegisterBankInfo.cpp  |  8 ++
 .../GlobalISel/llvm.amdgcn.ballot.i32.ll      | 77 +++++++++++++++++++
 .../GlobalISel/llvm.amdgcn.ballot.i64.ll      | 73 ++++++++++++++++++
 .../CodeGen/AMDGPU/llvm.amdgcn.ballot.i32.ll  | 64 ++++++---------
 .../CodeGen/AMDGPU/llvm.amdgcn.ballot.i64.ll  | 68 +++++++---------
 7 files changed, 246 insertions(+), 81 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
 create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index c3d5e78964c87..84734365cc658 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -891,6 +891,8 @@ bool AMDGPUInstructionSelector::selectG_INTRINSIC(MachineInstr &I) const {
     return selectDivScale(I);
   case Intrinsic::amdgcn_icmp:
     return selectIntrinsicIcmp(I);
+  case Intrinsic::amdgcn_ballot:
+    return selectBallot(I);
   default:
     return selectImpl(I, *CoverageInfo);
   }
@@ -1039,6 +1041,40 @@ bool AMDGPUInstructionSelector::selectIntrinsicIcmp(MachineInstr &I) const {
   return Ret;
 }
 
+bool AMDGPUInstructionSelector::selectBallot(MachineInstr &I) const {
+  MachineBasicBlock *BB = I.getParent();
+  const DebugLoc &DL = I.getDebugLoc();
+  Register DstReg = I.getOperand(0).getReg();
+  const unsigned Size = MRI->getType(DstReg).getSizeInBits();
+  const bool Is64 = Size == 64;
+
+  if (Size != STI.getWavefrontSize())
+    return false;
+
+  Optional Arg =
+      getConstantVRegValWithLookThrough(I.getOperand(2).getReg(), *MRI, true);
+
+  if (Arg.hasValue()) {
+    const int64_t Value = Arg.getValue().Value;
+    if (Value == 0) {
+      unsigned Opcode = Is64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
+      BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg).addImm(0);
+    } else if (Value == -1) { // all ones
+      Register SrcReg = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
+      const unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;
+      BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), DstReg)
+          .addReg(SrcReg, 0, SubReg);
+    } else
+      return false;
+  } else {
+    Register SrcReg = I.getOperand(2).getReg();
+    BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), DstReg).addReg(SrcReg);
+  }
+
+  I.eraseFromParent();
+  return true;
+}
+
 bool AMDGPUInstructionSelector::selectEndCfIntrinsic(MachineInstr &MI) const {
   // FIXME: Manually selecting to avoid dealiing with the SReg_1 trick
   // SelectionDAG uses for wave32 vs wave64.
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
index f8a8b5db4b556..1fe80958917d6 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h
@@ -107,6 +107,7 @@ class AMDGPUInstructionSelector : public InstructionSelector {
   bool selectInterpP1F16(MachineInstr &MI) const;
   bool selectDivScale(MachineInstr &MI) const;
   bool selectIntrinsicIcmp(MachineInstr &MI) const;
+  bool selectBallot(MachineInstr &I) const;
   bool selectG_INTRINSIC(MachineInstr &I) const;
 
   bool selectEndCfIntrinsic(MachineInstr &MI) const;
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
index 56bc0c44779d8..dfaf97bfb08e7 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
@@ -2989,6 +2989,7 @@ void AMDGPURegisterBankInfo::applyMappingImpl(
       constrainOpWithReadfirstlane(MI, MRI, 3); // Index
       return;
     }
+    case Intrinsic::amdgcn_ballot:
     case Intrinsic::amdgcn_interp_p1:
     case Intrinsic::amdgcn_interp_p2:
     case Intrinsic::amdgcn_interp_mov:
@@ -4160,6 +4161,13 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
       OpdsMapping[M0Idx] = AMDGPU::getValueMapping(M0Bank, 32);
       break;
     }
+    case Intrinsic::amdgcn_ballot: {
+      unsigned DstSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
+      unsigned SrcSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
+      OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, DstSize);
+      OpdsMapping[2] = AMDGPU::getValueMapping(AMDGPU::VCCRegBankID, SrcSize);
+      break;
+    }
     }
     break;
   }
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
new file mode 100644
index 0000000000000..b15fbf64fd8e2
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
@@ -0,0 +1,77 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -march=amdgcn -mcpu=gfx1010 -mattr=+wavefrontsize32,-wavefrontsize64 -global-isel < %s | FileCheck %s
+
+declare i32 @llvm.amdgcn.ballot.i32(i1)
+
+; Test ballot(0)
+
+define amdgpu_cs i32 @constant_false() {
+; CHECK-LABEL: constant_false:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_mov_b32 s0, 0
+; CHECK-NEXT:    ; implicit-def: $vcc_hi
+; CHECK-NEXT:    ; return to shader part epilog
+  %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 0)
+  ret i32 %ballot
+}
+
+; Test ballot(1)
+
+define amdgpu_cs i32 @constant_true() {
+; CHECK-LABEL: constant_true:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_mov_b32 s0, exec_lo
+; CHECK-NEXT:    ; implicit-def: $vcc_hi
+; CHECK-NEXT:    ; return to shader part epilog
+  %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 1)
+  ret i32 %ballot
+}
+
+; Test ballot of a non-comparison operation
+
+define amdgpu_cs i32 @non_compare(i32 %x) {
+; CHECK-LABEL: non_compare:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    v_and_b32_e32 v0, 1, v0
+; CHECK-NEXT:    ; implicit-def: $vcc_hi
+; CHECK-NEXT:    v_cmp_ne_u32_e64 s0, 0, v0
+; CHECK-NEXT:    ; return to shader part epilog
+  %trunc = trunc i32 %x to i1
+  %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %trunc)
+  ret i32 %ballot
+}
+
+; Test ballot of comparisons
+
+define amdgpu_cs i32 @compare_ints(i32 %x, i32 %y) {
+; CHECK-LABEL: compare_ints:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    v_cmp_eq_u32_e64 s0, v0, v1
+; CHECK-NEXT:    ; implicit-def: $vcc_hi
+; CHECK-NEXT:    ; return to shader part epilog
+  %cmp = icmp eq i32 %x, %y
+  %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %cmp)
+  ret i32 %ballot
+}
+
+define amdgpu_cs i32 @compare_int_with_constant(i32 %x) {
+; CHECK-LABEL: compare_int_with_constant:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    v_cmp_le_i32_e64 s0, 0x63, v0
+; CHECK-NEXT:    ; implicit-def: $vcc_hi
+; CHECK-NEXT:    ; return to shader part epilog
+  %cmp = icmp sge i32 %x, 99
+  %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %cmp)
+  ret i32 %ballot
+}
+
+define amdgpu_cs i32 @compare_floats(float %x, float %y) {
+; CHECK-LABEL: compare_floats:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    v_cmp_gt_f32_e64 s0, v0, v1
+; CHECK-NEXT:    ; implicit-def: $vcc_hi
+; CHECK-NEXT:    ; return to shader part epilog
+  %cmp = fcmp ogt float %x, %y
+  %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %cmp)
+  ret i32 %ballot
+}
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll
new file mode 100644
index 0000000000000..fcea5f8c9c59e
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll
@@ -0,0 +1,73 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -march=amdgcn -mcpu=gfx900 -global-isel < %s | FileCheck %s
+
+declare i64 @llvm.amdgcn.ballot.i64(i1)
+
+; Test ballot(0)
+
+define amdgpu_cs i64 @constant_false() {
+; CHECK-LABEL: constant_false:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_mov_b32 s0, 0
+; CHECK-NEXT:    s_mov_b32 s1, 0
+; CHECK-NEXT:    ; return to shader part epilog
+  %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 0)
+  ret i64 %ballot
+}
+
+; Test ballot(1)
+
+define amdgpu_cs i64 @constant_true() {
+; CHECK-LABEL: constant_true:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_mov_b64 s[0:1], exec
+; CHECK-NEXT:    ; return to shader part epilog
+  %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 1)
+  ret i64 %ballot
+}
+
+; Test ballot of a non-comparison operation
+
+define amdgpu_cs i64 @non_compare(i32 %x) {
+; CHECK-LABEL: non_compare:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    v_and_b32_e32 v0, 1, v0
+; CHECK-NEXT:    v_cmp_ne_u32_e64 s[0:1], 0, v0
+; CHECK-NEXT:    ; return to shader part epilog
+  %trunc = trunc i32 %x to i1
+  %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %trunc)
+  ret i64 %ballot
+}
+
+; Test ballot of comparisons
+
+define amdgpu_cs i64 @compare_ints(i32 %x, i32 %y) {
+; CHECK-LABEL: compare_ints:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    v_cmp_eq_u32_e64 s[0:1], v0, v1
+; CHECK-NEXT:    ; return to shader part epilog
+  %cmp = icmp eq i32 %x, %y
+  %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %cmp)
+  ret i64 %ballot
+}
+
+define amdgpu_cs i64 @compare_int_with_constant(i32 %x) {
+; CHECK-LABEL: compare_int_with_constant:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    v_mov_b32_e32 v1, 0x63
+; CHECK-NEXT:    v_cmp_ge_i32_e64 s[0:1], v0, v1
+; CHECK-NEXT:    ; return to shader part epilog
+  %cmp = icmp sge i32 %x, 99
+  %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %cmp)
+  ret i64 %ballot
+}
+
+define amdgpu_cs i64 @compare_floats(float %x, float %y) {
+; CHECK-LABEL: compare_floats:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    v_cmp_gt_f32_e64 s[0:1], v0, v1
+; CHECK-NEXT:    ; return to shader part epilog
+  %cmp = fcmp ogt float %x, %y
+  %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %cmp)
+  ret i64 %ballot
+}
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ballot.i32.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ballot.i32.ll
index c2aa65bddb7e0..20ef90db98319 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ballot.i32.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ballot.i32.ll
@@ -5,44 +5,37 @@ declare i32 @llvm.amdgcn.ballot.i32(i1)
 
 ; Test ballot(0)
 
-define i32 @test0() {
-; CHECK-LABEL: test0:
+define amdgpu_cs i32 @constant_false() {
+; CHECK-LABEL: constant_false:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    s_waitcnt_vscnt null, 0x0
-; CHECK-NEXT:    v_mov_b32_e32 v0, 0
+; CHECK-NEXT:    s_mov_b32 s0, 0
 ; CHECK-NEXT:    ; implicit-def: $vcc_hi
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    ; return to shader part epilog
   %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 0)
   ret i32 %ballot
 }
 
 ; Test ballot(1)
 
-define i32 @test1() {
-; CHECK-LABEL: test1:
+define amdgpu_cs i32 @constant_true() {
+; CHECK-LABEL: constant_true:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    s_waitcnt_vscnt null, 0x0
-; CHECK-NEXT:    v_mov_b32_e32 v0, exec_lo
+; CHECK-NEXT:    s_mov_b32 s0, exec_lo
 ; CHECK-NEXT:    ; implicit-def: $vcc_hi
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    ; return to shader part epilog
   %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 1)
   ret i32 %ballot
 }
 
 ; Test ballot of a non-comparison operation
 
-define i32 @test2(i32 %x) {
-; CHECK-LABEL: test2:
+define amdgpu_cs i32 @non_compare(i32 %x) {
+; CHECK-LABEL: non_compare:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    s_waitcnt_vscnt null, 0x0
 ; CHECK-NEXT:    v_and_b32_e32 v0, 1, v0
 ; CHECK-NEXT:    ; implicit-def: $vcc_hi
-; CHECK-NEXT:    v_cmp_ne_u32_e64 s4, 0, v0
-; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    v_cmp_ne_u32_e64 s0, 0, v0
+; CHECK-NEXT:    ; return to shader part epilog
   %trunc = trunc i32 %x to i1
   %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %trunc)
   ret i32 %ballot
@@ -50,43 +43,34 @@ define i32 @test2(i32 %x) {
 
 ; Test ballot of comparisons
 
-define i32 @test3(i32 %x, i32 %y) {
-; CHECK-LABEL: test3:
+define amdgpu_cs i32 @compare_ints(i32 %x, i32 %y) {
+; CHECK-LABEL: compare_ints:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    s_waitcnt_vscnt null, 0x0
-; CHECK-NEXT:    v_cmp_eq_u32_e64 s4, v0, v1
+; CHECK-NEXT:    v_cmp_eq_u32_e64 s0, v0, v1
 ; CHECK-NEXT:    ; implicit-def: $vcc_hi
-; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    ; return to shader part epilog
   %cmp = icmp eq i32 %x, %y
   %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %cmp)
   ret i32 %ballot
 }
 
-define i32 @test4(i32 %x) {
-; CHECK-LABEL: test4:
+define amdgpu_cs i32 @compare_int_with_constant(i32 %x) {
+; CHECK-LABEL: compare_int_with_constant:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    s_waitcnt_vscnt null, 0x0
-; CHECK-NEXT:    v_cmp_lt_i32_e64 s4, 0x62, v0
+; CHECK-NEXT:    v_cmp_lt_i32_e64 s0, 0x62, v0
 ; CHECK-NEXT:    ; implicit-def: $vcc_hi
-; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    ; return to shader part epilog
   %cmp = icmp sge i32 %x, 99
   %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %cmp)
   ret i32 %ballot
 }
 
-define i32 @test5(float %x, float %y) {
-; CHECK-LABEL: test5:
+define amdgpu_cs i32 @compare_floats(float %x, float %y) {
+; CHECK-LABEL: compare_floats:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    s_waitcnt_vscnt null, 0x0
-; CHECK-NEXT:    v_cmp_gt_f32_e64 s4, v0, v1
+; CHECK-NEXT:    v_cmp_gt_f32_e64 s0, v0, v1
 ; CHECK-NEXT:    ; implicit-def: $vcc_hi
-; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    ; return to shader part epilog
   %cmp = fcmp ogt float %x, %y
   %ballot = call i32 @llvm.amdgcn.ballot.i32(i1 %cmp)
   ret i32 %ballot
diff --git a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ballot.i64.ll b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ballot.i64.ll
index 97678bf309cbc..69066011a56c4 100644
--- a/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ballot.i64.ll
+++ b/llvm/test/CodeGen/AMDGPU/llvm.amdgcn.ballot.i64.ll
@@ -5,41 +5,36 @@ declare i64 @llvm.amdgcn.ballot.i64(i1)
 
 ; Test ballot(0)
 
-define i64 @test0() {
-; CHECK-LABEL: test0:
+define amdgpu_cs i64 @constant_false() {
+; CHECK-LABEL: constant_false:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    v_mov_b32_e32 v0, 0
-; CHECK-NEXT:    v_mov_b32_e32 v1, 0
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    s_mov_b32 s0, 0
+; CHECK-NEXT:    s_mov_b32 s1, 0
+; CHECK-NEXT:    ; return to shader part epilog
   %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 0)
   ret i64 %ballot
 }
 
 ; Test ballot(1)
 
-define i64 @test1() {
-; CHECK-LABEL: test1:
+define amdgpu_cs i64 @constant_true() {
+; CHECK-LABEL: constant_true:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    v_mov_b32_e32 v0, exec_lo
-; CHECK-NEXT:    v_mov_b32_e32 v1, exec_hi
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    s_mov_b32 s0, exec_lo
+; CHECK-NEXT:    s_mov_b32 s1, exec_hi
+; CHECK-NEXT:    ; return to shader part epilog
   %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 1)
   ret i64 %ballot
 }
 
 ; Test ballot of a non-comparison operation
 
-define i64 @test2(i32 %x) {
-; CHECK-LABEL: test2:
+define amdgpu_cs i64 @non_compare(i32 %x) {
+; CHECK-LABEL: non_compare:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; CHECK-NEXT:    v_and_b32_e32 v0, 1, v0
-; CHECK-NEXT:    v_cmp_ne_u32_e64 s[4:5], 0, v0
-; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    v_mov_b32_e32 v1, s5
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    v_cmp_ne_u32_e64 s[0:1], 0, v0
+; CHECK-NEXT:    ; return to shader part epilog
   %trunc = trunc i32 %x to i1
   %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %trunc)
   ret i64 %ballot
@@ -47,41 +42,32 @@ define i64 @test2(i32 %x) {
 
 ; Test ballot of comparisons
 
-define i64 @test3(i32 %x, i32 %y) {
-; CHECK-LABEL: test3:
+define amdgpu_cs i64 @compare_ints(i32 %x, i32 %y) {
+; CHECK-LABEL: compare_ints:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    v_cmp_eq_u32_e64 s[4:5], v0, v1
-; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    v_mov_b32_e32 v1, s5
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    v_cmp_eq_u32_e64 s[0:1], v0, v1
+; CHECK-NEXT:    ; return to shader part epilog
   %cmp = icmp eq i32 %x, %y
   %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %cmp)
   ret i64 %ballot
 }
 
-define i64 @test4(i32 %x) {
-; CHECK-LABEL: test4:
+define amdgpu_cs i64 @compare_int_with_constant(i32 %x) {
+; CHECK-LABEL: compare_int_with_constant:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    s_movk_i32 s4, 0x62
-; CHECK-NEXT:    v_cmp_lt_i32_e64 s[4:5], s4, v0
-; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    v_mov_b32_e32 v1, s5
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    s_movk_i32 s0, 0x62
+; CHECK-NEXT:    v_cmp_lt_i32_e64 s[0:1], s0, v0
+; CHECK-NEXT:    ; return to shader part epilog
   %cmp = icmp sge i32 %x, 99
   %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %cmp)
   ret i64 %ballot
 }
 
-define i64 @test5(float %x, float %y) {
-; CHECK-LABEL: test5:
+define amdgpu_cs i64 @compare_floats(float %x, float %y) {
+; CHECK-LABEL: compare_floats:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT:    v_cmp_gt_f32_e64 s[4:5], v0, v1
-; CHECK-NEXT:    v_mov_b32_e32 v0, s4
-; CHECK-NEXT:    v_mov_b32_e32 v1, s5
-; CHECK-NEXT:    s_setpc_b64 s[30:31]
+; CHECK-NEXT:    v_cmp_gt_f32_e64 s[0:1], v0, v1
+; CHECK-NEXT:    ; return to shader part epilog
   %cmp = fcmp ogt float %x, %y
   %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 %cmp)
   ret i64 %ballot

From 3bffe6022cc96a38ad0f6ada5f5b7b41eca5796e Mon Sep 17 00:00:00 2001
From: Benjamin Kramer 
Date: Mon, 13 Jul 2020 12:23:53 +0200
Subject: [PATCH 078/771] [mlir][VectorOps] Lower vector.fma to llvm.fmuladd
 instead of llvm.fma

Summary:
These are semantically equivalent, but fmuladd allows decaying the op
into fmul+fadd if there is no fma instruction available. llvm.fma lowers
to scalar calls to libm fmaf, which is a lot slower.

Reviewers: nicolasvasilache, aartbik, ftynse

Subscribers: mehdi_amini, rriddle, jpienaar, shauheen, antiagainst, arpith-jacob, mgester, lucyrfox, liufengdb, stephenneuendorffer, Joonsoo, grosul1, Kayjukh, jurahul, msifontes

Tags: #mlir

Differential Revision: https://reviews.llvm.org/D83666
---
 .../Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp    |  6 +++---
 mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir  | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
index 96a8fa4c6f223..2be2bd9bb7d02 100644
--- a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
+++ b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp
@@ -481,7 +481,7 @@ class VectorExtractOpConversion : public ConvertToLLVMPattern {
 /// ```
 /// is converted to:
 /// ```
-///  llvm.intr.fma %va, %va, %va:
+///  llvm.intr.fmuladd %va, %va, %va:
 ///    (!llvm<"<8 x float>">, !llvm<"<8 x float>">, !llvm<"<8 x float>">)
 ///    -> !llvm<"<8 x float>">
 /// ```
@@ -500,8 +500,8 @@ class VectorFMAOp1DConversion : public ConvertToLLVMPattern {
     VectorType vType = fmaOp.getVectorType();
     if (vType.getRank() != 1)
       return failure();
-    rewriter.replaceOpWithNewOp(op, adaptor.lhs(), adaptor.rhs(),
-                                             adaptor.acc());
+    rewriter.replaceOpWithNewOp(op, adaptor.lhs(),
+                                                 adaptor.rhs(), adaptor.acc());
     return success();
   }
 };
diff --git a/mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir b/mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir
index 09162aa0236ba..829edf5f66f17 100644
--- a/mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir
+++ b/mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir
@@ -236,7 +236,7 @@ func @outerproduct_add(%arg0: vector<2xf32>, %arg1: vector<3xf32>, %arg2: vector
 //      CHECK: %[[T5:.*]] = llvm.insertelement %[[T2]], %[[T3]][%[[T4]] : !llvm.i32] : !llvm<"<3 x float>">
 //      CHECK: %[[T6:.*]] = llvm.shufflevector %[[T5]], %[[T3]] [0 : i32, 0 : i32, 0 : i32] : !llvm<"<3 x float>">, !llvm<"<3 x float>">
 //      CHECK: %[[T7:.*]] = llvm.extractvalue %[[C]][0] : !llvm<"[2 x <3 x float>]">
-//      CHECK: %[[T8:.*]] = "llvm.intr.fma"(%[[T6]], %[[B]], %[[T7]]) : (!llvm<"<3 x float>">, !llvm<"<3 x float>">, !llvm<"<3 x float>">)
+//      CHECK: %[[T8:.*]] = "llvm.intr.fmuladd"(%[[T6]], %[[B]], %[[T7]]) : (!llvm<"<3 x float>">, !llvm<"<3 x float>">, !llvm<"<3 x float>">)
 //      CHECK: %[[T9:.*]] = llvm.insertvalue %[[T8]], %[[T0]][0] : !llvm<"[2 x <3 x float>]">
 //      CHECK: %[[T10:.*]] = llvm.mlir.constant(1 : i64) : !llvm.i64
 //      CHECK: %[[T11:.*]] = llvm.extractelement %[[A]][%[[T10]] : !llvm.i64] : !llvm<"<2 x float>">
@@ -245,7 +245,7 @@ func @outerproduct_add(%arg0: vector<2xf32>, %arg1: vector<3xf32>, %arg2: vector
 //      CHECK: %[[T14:.*]] = llvm.insertelement %[[T11]], %[[T12]][%[[T13]] : !llvm.i32] : !llvm<"<3 x float>">
 //      CHECK: %[[T15:.*]] = llvm.shufflevector %[[T14]], %[[T12]] [0 : i32, 0 : i32, 0 : i32] : !llvm<"<3 x float>">, !llvm<"<3 x float>">
 //      CHECK: %[[T16:.*]] = llvm.extractvalue %[[C]][1] : !llvm<"[2 x <3 x float>]">
-//      CHECK: %[[T17:.*]] = "llvm.intr.fma"(%[[T15]], %[[B]], %[[T16]]) : (!llvm<"<3 x float>">, !llvm<"<3 x float>">, !llvm<"<3 x float>">)
+//      CHECK: %[[T17:.*]] = "llvm.intr.fmuladd"(%[[T15]], %[[B]], %[[T16]]) : (!llvm<"<3 x float>">, !llvm<"<3 x float>">, !llvm<"<3 x float>">)
 //      CHECK: %[[T18:.*]] = llvm.insertvalue %[[T17]], %[[T9]][1] : !llvm<"[2 x <3 x float>]">
 //      CHECK: llvm.return %[[T18]] : !llvm<"[2 x <3 x float>]">
 
@@ -688,20 +688,20 @@ func @extract_strides(%arg0: vector<3x3xf32>) -> vector<1x1xf32> {
 //  CHECK-SAME: %[[A:.*]]: !llvm<"<8 x float>">, %[[B:.*]]: !llvm<"[2 x <4 x float>]">)
 //  CHECK-SAME: -> !llvm<"{ <8 x float>, [2 x <4 x float>] }"> {
 func @vector_fma(%a: vector<8xf32>, %b: vector<2x4xf32>) -> (vector<8xf32>, vector<2x4xf32>) {
-  //         CHECK: "llvm.intr.fma"(%[[A]], %[[A]], %[[A]]) :
+  //         CHECK: "llvm.intr.fmuladd"(%[[A]], %[[A]], %[[A]]) :
   //    CHECK-SAME:   (!llvm<"<8 x float>">, !llvm<"<8 x float>">, !llvm<"<8 x float>">) -> !llvm<"<8 x float>">
   %0 = vector.fma %a, %a, %a : vector<8xf32>
 
   //       CHECK: %[[b00:.*]] = llvm.extractvalue %[[B]][0] : !llvm<"[2 x <4 x float>]">
   //       CHECK: %[[b01:.*]] = llvm.extractvalue %[[B]][0] : !llvm<"[2 x <4 x float>]">
   //       CHECK: %[[b02:.*]] = llvm.extractvalue %[[B]][0] : !llvm<"[2 x <4 x float>]">
-  //       CHECK: %[[B0:.*]] = "llvm.intr.fma"(%[[b00]], %[[b01]], %[[b02]]) :
+  //       CHECK: %[[B0:.*]] = "llvm.intr.fmuladd"(%[[b00]], %[[b01]], %[[b02]]) :
   //  CHECK-SAME: (!llvm<"<4 x float>">, !llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
   //       CHECK: llvm.insertvalue %[[B0]], {{.*}}[0] : !llvm<"[2 x <4 x float>]">
   //       CHECK: %[[b10:.*]] = llvm.extractvalue %[[B]][1] : !llvm<"[2 x <4 x float>]">
   //       CHECK: %[[b11:.*]] = llvm.extractvalue %[[B]][1] : !llvm<"[2 x <4 x float>]">
   //       CHECK: %[[b12:.*]] = llvm.extractvalue %[[B]][1] : !llvm<"[2 x <4 x float>]">
-  //       CHECK: %[[B1:.*]] = "llvm.intr.fma"(%[[b10]], %[[b11]], %[[b12]]) :
+  //       CHECK: %[[B1:.*]] = "llvm.intr.fmuladd"(%[[b10]], %[[b11]], %[[b12]]) :
   //  CHECK-SAME: (!llvm<"<4 x float>">, !llvm<"<4 x float>">, !llvm<"<4 x float>">) -> !llvm<"<4 x float>">
   //       CHECK: llvm.insertvalue %[[B1]], {{.*}}[1] : !llvm<"[2 x <4 x float>]">
   %1 = vector.fma %b, %b, %b : vector<2x4xf32>

From 6050c156ab4f13a3c54ca6ec297a72ece95966d7 Mon Sep 17 00:00:00 2001
From: Anastasia Stulova 
Date: Mon, 13 Jul 2020 11:30:13 +0100
Subject: [PATCH 079/771] [OpenCL] Defer addr space deduction for dependent
 type.

This patch removes deduction of address spaces in parsing
for types that depend on template parameter even if an
address space is already known. Deducing it early interferes
with template instantiation/specialization logic that uses
source address space where address space is not present.

Address space deduction for templates is therefore fully
moved to the template instantiation/specialization phase.

Patch by Ole Strohm (olestrohm)!

Tags: #clang

Differential Revision: https://reviews.llvm.org/D82781
---
 clang/lib/Sema/SemaDecl.cpp                     |  3 +++
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp  |  6 ++++++
 .../SemaOpenCLCXX/address-space-deduction.cl    | 17 ++++++++++++-----
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f5e375134c293..3e2b61ae8cdf6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6290,6 +6290,8 @@ bool Sema::inferObjCARCLifetime(ValueDecl *decl) {
 void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) {
   if (Decl->getType().hasAddressSpace())
     return;
+  if (Decl->getType()->isDependentType())
+    return;
   if (VarDecl *Var = dyn_cast(Decl)) {
     QualType Type = Var->getType();
     if (Type->isSamplerT() || Type->isVoidType())
@@ -7859,6 +7861,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
     if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() ||
         NewVD->hasExternalStorage()) {
       if (!T->isSamplerT() &&
+          !T->isDependentType() &&
           !(T.getAddressSpace() == LangAS::opencl_constant ||
             (T.getAddressSpace() == LangAS::opencl_global &&
              (getLangOpts().OpenCLVersion == 200 ||
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 85adc4ef2dbde..2efb7acb97245 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3625,6 +3625,9 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
   if (InsertPos)
     VarTemplate->AddSpecialization(Var, InsertPos);
 
+  if (SemaRef.getLangOpts().OpenCL)
+    SemaRef.deduceOpenCLAddressSpace(Var);
+
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
     return nullptr;
@@ -4895,6 +4898,9 @@ VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl(
   // Instantiate the initializer.
   InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
 
+  if (getLangOpts().OpenCL)
+    deduceOpenCLAddressSpace(VarSpec);
+
   return VarSpec;
 }
 
diff --git a/clang/test/SemaOpenCLCXX/address-space-deduction.cl b/clang/test/SemaOpenCLCXX/address-space-deduction.cl
index 6a81a8b2d7c76..ddfdb6da4347c 100644
--- a/clang/test/SemaOpenCLCXX/address-space-deduction.cl
+++ b/clang/test/SemaOpenCLCXX/address-space-deduction.cl
@@ -5,6 +5,11 @@
 //CHECK: |-VarDecl {{.*}} foo 'const __global int'
 constexpr int foo = 0;
 
+//CHECK: |-VarDecl {{.*}} foo1 'T' cinit
+//CHECK: `-VarTemplateSpecializationDecl {{.*}} used foo1 '__global long':'__global long' cinit
+template 
+T foo1 = 0;
+
 class c {
 public:
   //CHECK: `-VarDecl {{.*}} foo2 'const __global int'
@@ -30,7 +35,7 @@ struct c2 {
 
 template 
 struct x1 {
-//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &){{( __attribute__.*)?}} __generic'
 //CHECK: -CXXMethodDecl {{.*}} operator= '__generic x1 &(const __generic x1 &__private){{( __attribute__.*)?}} __generic'
   x1& operator=(const x1& xx) {
     y = xx.y;
@@ -41,7 +46,7 @@ struct x1 {
 
 template 
 struct x2 {
-//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *){{( __attribute__.*)?}} __generic'
 //CHECK: -CXXMethodDecl {{.*}} foo 'void (__generic x1 *__private){{( __attribute__.*)?}} __generic'
   void foo(x1* xx) {
     m[0] = *xx;
@@ -57,10 +62,10 @@ void bar(__global x1 *xx, __global x2 *bar) {
 template 
 class x3 : public T {
 public:
-  //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &__private){{( __attribute__.*)?}} __generic'
+  //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic'
   x3(const x3 &t);
 };
-//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic'
 template 
 x3::x3(const x3 &t) {}
 
@@ -68,7 +73,8 @@ template 
 T xxx(T *in1, T in2) {
   // This pointer can't be deduced to generic because addr space
   // will be taken from the template argument.
-  //CHECK: `-VarDecl {{.*}} '__private T *__private' cinit
+  //CHECK: `-VarDecl {{.*}} 'T *' cinit
+  //CHECK: `-VarDecl {{.*}} i '__private int *__private' cinit
   T *i = in1;
   T ii;
   __private T *ptr = ⅈ
@@ -111,4 +117,5 @@ __kernel void k() {
   t3(&x);
   t4(&p);
   t5(&p);
+  long f1 = foo1;
 }

From af16a45683cccc78925e71ac5d58d6cab8447840 Mon Sep 17 00:00:00 2001
From: Georgii Rymar 
Date: Thu, 9 Jul 2020 13:08:13 +0300
Subject: [PATCH 080/771] [LLD][ELF] -  Allow relocation sections to appear
 before their target sections.

It allows handling cases when we have SHT_REL[A] sections before target
sections in objects.

This fixes https://bugs.llvm.org/show_bug.cgi?id=46632

which says: "Normally it is not what compilers would emit. We have to support it,
because some custom tools might want to use this feature, which is not restricted by ELF gABI"

Differential revision: https://reviews.llvm.org/D83469
---
 lld/ELF/InputFiles.cpp                        | 14 ++++++-
 .../ELF/invalid/reloc-section-reordered.test  | 33 ----------------
 lld/test/ELF/reloc-sec-before-relocated.test  | 38 +++++++++++++++++++
 3 files changed, 51 insertions(+), 34 deletions(-)
 delete mode 100644 lld/test/ELF/invalid/reloc-section-reordered.test
 create mode 100644 lld/test/ELF/reloc-sec-before-relocated.test

diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index e59bf626be501..c2f1830a981b8 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -632,6 +632,8 @@ void ObjFile::initializeSections(bool ignoreComdats) {
       break;
     case SHT_SYMTAB:
     case SHT_STRTAB:
+    case SHT_REL:
+    case SHT_RELA:
     case SHT_NULL:
       break;
     default:
@@ -639,11 +641,21 @@ void ObjFile::initializeSections(bool ignoreComdats) {
     }
   }
 
-  // This block handles SHF_LINK_ORDER.
+  // We have a second loop. It is used to:
+  // 1) handle SHF_LINK_ORDER sections.
+  // 2) create SHT_REL[A] sections. In some cases the section header index of a
+  //    relocation section may be smaller than that of the relocated section. In
+  //    such cases, the relocation section would attempt to reference a target
+  //    section that has not yet been created. For simplicity, delay creation of
+  //    relocation sections until now.
   for (size_t i = 0, e = objSections.size(); i < e; ++i) {
     if (this->sections[i] == &InputSection::discarded)
       continue;
     const Elf_Shdr &sec = objSections[i];
+
+    if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA)
+      this->sections[i] = createInputSection(sec);
+
     if (!(sec.sh_flags & SHF_LINK_ORDER))
       continue;
 
diff --git a/lld/test/ELF/invalid/reloc-section-reordered.test b/lld/test/ELF/invalid/reloc-section-reordered.test
deleted file mode 100644
index 91f25f61b7e6f..0000000000000
--- a/lld/test/ELF/invalid/reloc-section-reordered.test
+++ /dev/null
@@ -1,33 +0,0 @@
-# REQUIRES: x86
-
-# RUN: yaml2obj %s -o %t.o
-# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
-# CHECK: unsupported relocation reference
-
-## YAML below lists .rela.text before .text, we do not support it.
-
-!ELF
-FileHeader:
-  Class:           ELFCLASS64
-  Data:            ELFDATA2LSB
-  OSABI:           ELFOSABI_FREEBSD
-  Type:            ET_REL
-  Machine:         EM_X86_64
-Sections:
-  - Type:            SHT_REL
-    Name:            .rela.text
-    Link:            .symtab
-    Info:            .text
-    AddressAlign:    0x04
-    Relocations:
-      - Symbol:          .text
-        Type:            R_X86_64_NONE
-  - Type:            SHT_PROGBITS
-    Name:            .text
-    Flags:           [ SHF_ALLOC, SHF_EXECINSTR ]
-    AddressAlign:    0x04
-    Content:         "FFFFFFFFFFFFFFFF"
-Symbols:
-  - Name:    .text
-    Type:    STT_SECTION
-    Section: .text
diff --git a/lld/test/ELF/reloc-sec-before-relocated.test b/lld/test/ELF/reloc-sec-before-relocated.test
new file mode 100644
index 0000000000000..a56231294a0ca
--- /dev/null
+++ b/lld/test/ELF/reloc-sec-before-relocated.test
@@ -0,0 +1,38 @@
+## If the section header index of a SHT_REL[A] section is smaller than the
+## section header index of the relocated section, we should handle it properly.
+## Normally it is not what compilers would emit, but some custom tools might
+## want to use this feature, which is not restricted by ELF gABI.
+## GNU ld supports this as well.
+
+# RUN: yaml2obj %s -DTYPE=SHT_RELA -o %t1.o
+# RUN: ld.lld -shared %t1.o -o %t1
+# RUN: llvm-readelf --relocs %t1 | FileCheck %s
+
+# RUN: yaml2obj %s -DTYPE=SHT_REL -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t2
+# RUN: llvm-readelf --relocs %t2 | FileCheck %s
+
+## Check we handle the relocation properly.
+# CHECK:      Relocation section '.rela.dyn' at offset 0x238 contains 1 entries:
+# CHECK-NEXT:     Offset             Info             Type    Symbol's Value  Symbol's Name + Addend
+# CHECK-NEXT: 00000000000022f0  0000000100000001 R_X86_64_64 0000000000000000 foo + 0
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:  .relx.data
+    Type:  [[TYPE]]
+    Info:  .data
+    Relocations:
+      - Symbol: foo
+        Type:   R_X86_64_64
+  - Name:  .data
+    Type:  SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_WRITE ]
+Symbols:
+  - Name:    foo
+    Binding: STB_GLOBAL

From 6bda276f93023ae91937cb8a1f45bf27e5a3ced7 Mon Sep 17 00:00:00 2001
From: Ben Dunbobbin 
Date: Mon, 13 Jul 2020 11:58:30 +0100
Subject: [PATCH 081/771] [LLD][ELF][Windows] small improvement to D82567

Bail early if there is no existing output file to be overwritten.

Differential Revision: https://reviews.llvm.org/D83272
---
 lld/Common/Filesystem.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lld/Common/Filesystem.cpp b/lld/Common/Filesystem.cpp
index 206b892f0a69c..671b352a3f6bc 100644
--- a/lld/Common/Filesystem.cpp
+++ b/lld/Common/Filesystem.cpp
@@ -40,6 +40,9 @@ using namespace lld;
 // This function spawns a background thread to remove the file.
 // The calling thread returns almost immediately.
 void lld::unlinkAsync(StringRef path) {
+  if (!sys::fs::exists(path) || !sys::fs::is_regular_file(path))
+    return;
+
 // Removing a file is async on windows.
 #if defined(_WIN32)
   // On Windows co-operative programs can be expected to open LLD's
@@ -71,8 +74,7 @@ void lld::unlinkAsync(StringRef path) {
   }
   sys::fs::remove(path);
 #else
-  if (parallel::strategy.ThreadsRequested == 1 || !sys::fs::exists(path) ||
-      !sys::fs::is_regular_file(path))
+  if (parallel::strategy.ThreadsRequested == 1)
     return;
 
   // We cannot just remove path from a different thread because we are now going

From c051312eb24dedc119a917ea23e6a5810f5758ff Mon Sep 17 00:00:00 2001
From: Andre Vieira 
Date: Mon, 13 Jul 2020 11:52:58 +0100
Subject: [PATCH 082/771] [libc][benchmark] Add display option to render.py3

Differential Revision: https://reviews.llvm.org/D83380
---
 libc/benchmarks/render.py3 | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/libc/benchmarks/render.py3 b/libc/benchmarks/render.py3
index e790d18f84e7f..f8c321ff17af6 100644
--- a/libc/benchmarks/render.py3
+++ b/libc/benchmarks/render.py3
@@ -112,7 +112,7 @@ def get_configuration(jsons):
     return config
 
 
-def setup_graphs(files):
+def setup_graphs(files, display):
     """Setups the graphs to render from the json files."""
     jsons = []
     for file in files:
@@ -122,6 +122,7 @@ def setup_graphs(files):
         sys.exit("Nothing to process")
 
     for root in jsons:
+        frequency = root["Host"]["CpuFrequency"]
         for function in root["Functions"]:
             function_name = function["Name"]
             sizes = function["Sizes"]
@@ -129,7 +130,13 @@ def setup_graphs(files):
             assert len(sizes) == len(runtimes)
             values = collections.defaultdict(lambda: [])
             for i in range(len(sizes)):
-              values[sizes[i]].append(runtimes[i])
+              value = runtimes[i]
+              if display == "cycles":
+                  value = value * frequency
+              if display == "bytespercycle":
+                  value = value * frequency
+                  value = sizes[i] / value
+              values[sizes[i]].append(value)
             add_plot(function_name, values)
 
     config = get_configuration(jsons)
@@ -148,9 +155,15 @@ def setup_graphs(files):
     axes.set_title(get_title(get_host(jsons)))
     axes.set_ylim(bottom=0)
     axes.set_xlabel("Size")
-    axes.set_ylabel("Time")
     axes.xaxis.set_major_formatter(EngFormatter(unit="B"))
-    axes.yaxis.set_major_formatter(EngFormatter(unit="s"))
+    if display == "cycles":
+          axes.set_ylabel("Cycles")
+    if display == "time":
+          axes.set_ylabel("Time")
+          axes.yaxis.set_major_formatter(EngFormatter(unit="s"))
+    if display == "bytespercycle":
+          axes.set_ylabel("bytes/cycle")
+
     plt.legend()
     plt.grid()
 
@@ -164,8 +177,14 @@ def main():
         "--headless",
         help="If set do not display the graph.",
         action="store_true")
+    parser.add_argument(
+        "--display",
+        choices= ["time", "cycles", "bytespercycle"],
+        default="time",
+        help="Use to display either 'time', 'cycles' or 'bytes/cycle'.")
+
     args = parser.parse_args()
-    setup_graphs(args.files)
+    setup_graphs(args.files, args.display)
     if args.output:
         plt.savefig(args.output)
     if not args.headless:

From 60cbbb306d29f882e18d6293177d694c11c67e84 Mon Sep 17 00:00:00 2001
From: Raphael Isemann 
Date: Mon, 13 Jul 2020 12:22:09 +0200
Subject: [PATCH 083/771] [lldb][NFC] Remove misleading class_language variable
 in DWARFASTParserClang

There is a local 'class_language' veriable in DWARFASTParserClang which is named
as if it is related to the 'class_language' member of ParsedDWARFTypeAttributes.
However, it actually only has two possible enum values: 'ObjC' (which means the
current record is a Objective-C class) or 'Unknown' (which covers all other
cases).

This is confusing for the reader and also lead to some strange code where we
have several comparisons against the value "ObjC_plus_plus" (which is always
false).

This replaces the variable with either a const bool variable (if there are
multiple checks for that condition in a function) or a direct call to the
TypeSystemClang utility method for checking if it's a Objective-C
Object/Interface type.
---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  | 32 +++++++++----------
 .../SymbolFile/DWARF/DWARFASTParserClang.h    |  2 --
 2 files changed, 15 insertions(+), 19 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 7de88274ccf6e..929001671af7d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -1958,9 +1958,9 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
   ClangASTImporter::LayoutInfo layout_info;
 
   if (die.HasChildren()) {
-    LanguageType class_language = eLanguageTypeUnknown;
-    if (TypeSystemClang::IsObjCObjectOrInterfaceType(clang_type)) {
-      class_language = eLanguageTypeObjC;
+    const bool type_is_objc_object_or_interface =
+        TypeSystemClang::IsObjCObjectOrInterfaceType(clang_type);
+    if (type_is_objc_object_or_interface) {
       // For objective C we don't start the definition when the class is
       // created.
       TypeSystemClang::StartTagDeclarationDefinition(clang_type);
@@ -1986,16 +1986,15 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
     std::vector member_function_dies;
 
     DelayedPropertyList delayed_properties;
-    ParseChildMembers(die, clang_type, class_language, bases,
-                      member_accessibilities, member_function_dies,
-                      delayed_properties, default_accessibility, is_a_class,
-                      layout_info);
+    ParseChildMembers(die, clang_type, bases, member_accessibilities,
+                      member_function_dies, delayed_properties,
+                      default_accessibility, is_a_class, layout_info);
 
     // Now parse any methods if there were any...
     for (const DWARFDIE &die : member_function_dies)
       dwarf->ResolveType(die);
 
-    if (class_language == eLanguageTypeObjC) {
+    if (type_is_objc_object_or_interface) {
       ConstString class_name(clang_type.GetTypeName());
       if (class_name) {
         dwarf->GetObjCMethods(class_name, [&](DWARFDIE method_die) {
@@ -2012,7 +2011,7 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
 
     // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
     // need to tell the clang type it is actually a class.
-    if (class_language != eLanguageTypeObjC) {
+    if (!type_is_objc_object_or_interface) {
       if (is_a_class && tag_decl_kind != clang::TTK_Class)
         m_ast.SetTagTypeKind(ClangUtil::GetQualType(clang_type),
                              clang::TTK_Class);
@@ -2346,7 +2345,6 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
 void DWARFASTParserClang::ParseSingleMember(
     const DWARFDIE &die, const DWARFDIE &parent_die,
     const lldb_private::CompilerType &class_clang_type,
-    const lldb::LanguageType class_language,
     std::vector &member_accessibilities,
     lldb::AccessType default_accessibility,
     DelayedPropertyList &delayed_properties,
@@ -2520,9 +2518,11 @@ void DWARFASTParserClang::ParseSingleMember(
       bit_offset = 0;
     }
 
+    const bool class_is_objc_object_or_interface =
+        TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type);
+
     // FIXME: Make Clang ignore Objective-C accessibility for expressions
-    if (class_language == eLanguageTypeObjC ||
-        class_language == eLanguageTypeObjC_plus_plus)
+    if (class_is_objc_object_or_interface)
       accessibility = eAccessNone;
 
     // Handle static members
@@ -2599,8 +2599,7 @@ void DWARFASTParserClang::ParseSingleMember(
             // unnamed bitfields if we have a new enough clang.
             bool detect_unnamed_bitfields = true;
 
-            if (class_language == eLanguageTypeObjC ||
-                class_language == eLanguageTypeObjC_plus_plus)
+            if (class_is_objc_object_or_interface)
               detect_unnamed_bitfields =
                   die.GetCU()->Supports_unnamed_objc_bitfields();
 
@@ -2754,7 +2753,6 @@ void DWARFASTParserClang::ParseSingleMember(
 
 bool DWARFASTParserClang::ParseChildMembers(
     const DWARFDIE &parent_die, CompilerType &class_clang_type,
-    const LanguageType class_language,
     std::vector> &base_classes,
     std::vector &member_accessibilities,
     std::vector &member_function_dies,
@@ -2778,7 +2776,7 @@ bool DWARFASTParserClang::ParseChildMembers(
     switch (tag) {
     case DW_TAG_member:
     case DW_TAG_APPLE_property:
-      ParseSingleMember(die, parent_die, class_clang_type, class_language,
+      ParseSingleMember(die, parent_die, class_clang_type,
                         member_accessibilities, default_accessibility,
                         delayed_properties, layout_info, last_field_info);
       break;
@@ -2868,7 +2866,7 @@ bool DWARFASTParserClang::ParseChildMembers(
         CompilerType base_class_clang_type =
             base_class_type->GetFullCompilerType();
         assert(base_class_clang_type);
-        if (class_language == eLanguageTypeObjC) {
+        if (TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type)) {
           ast->SetObjCSuperClass(class_clang_type, base_class_clang_type);
         } else {
           std::unique_ptr result =
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index cb718a207d2d4..2ef49abc1da16 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -110,7 +110,6 @@ class DWARFASTParserClang : public DWARFASTParser {
 
   bool ParseChildMembers(
       const DWARFDIE &die, lldb_private::CompilerType &class_compiler_type,
-      const lldb::LanguageType class_language,
       std::vector> &base_classes,
       std::vector &member_accessibilities,
       std::vector &member_function_dies,
@@ -195,7 +194,6 @@ class DWARFASTParserClang : public DWARFASTParser {
   void
   ParseSingleMember(const DWARFDIE &die, const DWARFDIE &parent_die,
                     const lldb_private::CompilerType &class_clang_type,
-                    const lldb::LanguageType class_language,
                     std::vector &member_accessibilities,
                     lldb::AccessType default_accessibility,
                     DelayedPropertyList &delayed_properties,

From 319a97b5e2620f9eb3618b629223253feacff92a Mon Sep 17 00:00:00 2001
From: Paul Walker 
Date: Mon, 13 Jul 2020 11:16:30 +0000
Subject: [PATCH 084/771] [SVE] Ensure fixed length vector fptrunc operations
 bigger than NEON are not considered legal.

Differential Revision: https://reviews.llvm.org/D83568
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  15 +-
 .../AArch64/sve-fixed-length-fp-converts.ll   | 168 ++++++++++++++++++
 2 files changed, 180 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/sve-fixed-length-fp-converts.ll

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 65ccc18ed6013..85db14ab66feb 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -963,12 +963,15 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
           addTypeForFixedLengthSVE(VT);
 
       // 64bit results can mean a bigger than NEON input.
-      for (auto VT : {MVT::v8i8, MVT::v4i16, MVT::v2i32})
+      for (auto VT : {MVT::v8i8, MVT::v4i16})
         setOperationAction(ISD::TRUNCATE, VT, Custom);
+      setOperationAction(ISD::FP_ROUND, MVT::v4f16, Custom);
 
       // 128bit results imply a bigger than NEON input.
       for (auto VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
         setOperationAction(ISD::TRUNCATE, VT, Custom);
+      for (auto VT : {MVT::v8f16, MVT::v4f32})
+        setOperationAction(ISD::FP_ROUND, VT, Expand);
     }
   }
 
@@ -2712,13 +2715,19 @@ SDValue AArch64TargetLowering::LowerFP_ROUND(SDValue Op,
                                              SelectionDAG &DAG) const {
   bool IsStrict = Op->isStrictFPOpcode();
   SDValue SrcVal = Op.getOperand(IsStrict ? 1 : 0);
-  if (SrcVal.getValueType() != MVT::f128) {
+  EVT SrcVT = SrcVal.getValueType();
+
+  if (SrcVT != MVT::f128) {
+    // Expand cases where the input is a vector bigger than NEON.
+    if (useSVEForFixedLengthVectorVT(SrcVT))
+      return SDValue();
+
     // It's legal except when f128 is involved
     return Op;
   }
 
   RTLIB::Libcall LC;
-  LC = RTLIB::getFPROUND(SrcVal.getValueType(), Op.getValueType());
+  LC = RTLIB::getFPROUND(SrcVT, Op.getValueType());
 
   // FP_ROUND node has a second operand indicating whether it is known to be
   // precise. That doesn't take part in the LibCall so we can't directly use
diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-fp-converts.ll b/llvm/test/CodeGen/AArch64/sve-fixed-length-fp-converts.ll
new file mode 100644
index 0000000000000..4ffb56abe5f18
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-fp-converts.ll
@@ -0,0 +1,168 @@
+; RUN: llc -aarch64-sve-vector-bits-min=128  -asm-verbose=0 < %s | FileCheck %s -check-prefix=NO_SVE
+; RUN: llc -aarch64-sve-vector-bits-min=256  -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK
+; RUN: llc -aarch64-sve-vector-bits-min=384  -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK
+; RUN: llc -aarch64-sve-vector-bits-min=512  -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512
+; RUN: llc -aarch64-sve-vector-bits-min=640  -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512
+; RUN: llc -aarch64-sve-vector-bits-min=768  -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512
+; RUN: llc -aarch64-sve-vector-bits-min=896  -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512
+; RUN: llc -aarch64-sve-vector-bits-min=1024 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024
+; RUN: llc -aarch64-sve-vector-bits-min=1152 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024
+; RUN: llc -aarch64-sve-vector-bits-min=1280 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024
+; RUN: llc -aarch64-sve-vector-bits-min=1408 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024
+; RUN: llc -aarch64-sve-vector-bits-min=1536 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024
+; RUN: llc -aarch64-sve-vector-bits-min=1664 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024
+; RUN: llc -aarch64-sve-vector-bits-min=1792 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024
+; RUN: llc -aarch64-sve-vector-bits-min=1920 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024
+; RUN: llc -aarch64-sve-vector-bits-min=2048 -asm-verbose=0 < %s | FileCheck %s -check-prefixes=CHECK,VBITS_GE_512,VBITS_GE_1024,VBITS_GE_2048
+
+target triple = "aarch64-unknown-linux-gnu"
+
+; Don't use SVE when its registers are no bigger than NEON.
+; NO_SVE-NOT: z{0-9}
+
+; NOTE: fptrunc operations bigger than NEON are expanded. These tests just
+; ensure we've correctly set the operation action for fixed length vector types
+; that require SVE. They'll be updated to protect their expected code generation
+; when lowering it implemented.
+
+;
+; fptrunc f32 -> f16
+;
+
+define <8 x half> @fptrunc_v8f32_v8f16(<8 x float>* %in) #0 {
+; CHECK-LABEL: fptrunc_v8f32_v8f16:
+; CHECK-COUNT-8: fcvt h{{[0-9]}}, s{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <8 x float>, <8 x float>* %in
+  %b = fptrunc <8 x float> %a to <8 x half>
+  ret <8 x half> %b
+}
+
+define void @fptrunc_v16f32_v16f16(<16 x float>* %in, <16 x half>* %out) #0 {
+; CHECK-LABEL: fptrunc_v16f32_v16f16:
+; CHECK-COUNT-16: fcvt h{{[0-9]}}, s{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <16 x float>, <16 x float>* %in
+  %b = fptrunc <16 x float> %a to <16 x half>
+  store <16 x half> %b, <16 x half>* %out
+  ret void
+}
+
+define void @fptrunc_v32f32_v32f16(<32 x float>* %in, <32 x half>* %out) #0 {
+; CHECK-LABEL: fptrunc_v32f32_v32f16:
+; CHECK-COUNT-32: fcvt h{{[0-9]}}, s{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <32 x float>, <32 x float>* %in
+  %b = fptrunc <32 x float> %a to <32 x half>
+  store <32 x half> %b, <32 x half>* %out
+  ret void
+}
+
+define void @fptrunc_v64f32_v64f16(<64 x float>* %in, <64 x half>* %out) #0 {
+; CHECK-LABEL: fptrunc_v64f32_v64f16:
+; CHECK-COUNT-64: fcvt h{{[0-9]}}, s{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <64 x float>, <64 x float>* %in
+  %b = fptrunc <64 x float> %a to <64 x half>
+  store <64 x half> %b, <64 x half>* %out
+  ret void
+}
+
+;
+; fptrunc f64 -> f16
+;
+
+define <4 x half> @fptrunc_v4f64_v4f16(<4 x double>* %in) #0 {
+; CHECK-LABEL: fptrunc_v4f64_v4f16:
+; CHECK-COUNT-4: fcvt h{{[0-9]}}, d{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <4 x double>, <4 x double>* %in
+  %b = fptrunc <4 x double> %a to <4 x half>
+  ret <4 x half> %b
+}
+
+define <8 x half> @fptrunc_v8f64_v8f16(<8 x double>* %in) #0 {
+; CHECK-LABEL: fptrunc_v8f64_v8f16:
+; CHECK-COUNT-8: fcvt h{{[0-9]}}, d{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <8 x double>, <8 x double>* %in
+  %b = fptrunc <8 x double> %a to <8 x half>
+  ret <8 x half> %b
+}
+
+define void @fptrunc_v16f64_v16f16(<16 x double>* %in, <16 x half>* %out) #0 {
+; CHECK-LABEL: fptrunc_v16f64_v16f16:
+; CHECK-COUNT-16: fcvt h{{[0-9]}}, d{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <16 x double>, <16 x double>* %in
+  %b = fptrunc <16 x double> %a to <16 x half>
+  store <16 x half> %b, <16 x half>* %out
+  ret void
+}
+
+define void @fptrunc_v32f64_v32f16(<32 x double>* %in, <32 x half>* %out) #0 {
+; CHECK-LABEL: fptrunc_v32f64_v32f16:
+; CHECK-COUNT-32: fcvt h{{[0-9]}}, d{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <32 x double>, <32 x double>* %in
+  %b = fptrunc <32 x double> %a to <32 x half>
+  store <32 x half> %b, <32 x half>* %out
+  ret void
+}
+
+;
+; fptrunc f64 -> f32
+;
+
+define <4 x float> @fptrunc_v4f64_v4f32(<4 x double>* %in) #0 {
+; CHECK-LABEL: fptrunc_v4f64_v4f32:
+; CHECK-COUNT-4: fcvt s{{[0-9]}}, d{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <4 x double>, <4 x double>* %in
+  %b = fptrunc <4 x double> %a to <4 x float>
+  ret <4 x float> %b
+}
+
+define void @fptrunc_v8f64_v8f32(<8 x double>* %in, <8 x float>* %out) #0 {
+; CHECK-LABEL: fptrunc_v8f64_v8f32:
+; CHECK-COUNT-8: fcvt s{{[0-9]}}, d{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <8 x double>, <8 x double>* %in
+  %b = fptrunc <8 x double> %a to <8 x float>
+  store <8 x float> %b, <8 x float>* %out
+  ret void
+}
+
+define void @fptrunc_v16f64_v16f32(<16 x double>* %in, <16 x float>* %out) #0 {
+; CHECK-LABEL: fptrunc_v16f64_v16f32:
+; CHECK-COUNT-16: fcvt s{{[0-9]}}, d{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <16 x double>, <16 x double>* %in
+  %b = fptrunc <16 x double> %a to <16 x float>
+  store <16 x float> %b, <16 x float>* %out
+  ret void
+}
+
+define void @fptrunc_v32f64_v32f32(<32 x double>* %in, <32 x float>* %out) #0 {
+; CHECK-LABEL: fptrunc_v32f64_v32f32:
+; CHECK-COUNT-32: fcvt s{{[0-9]}}, d{{[0-9]}}
+; CHECK-NOT: fcvt
+; CHECK: ret
+  %a = load <32 x double>, <32 x double>* %in
+  %b = fptrunc <32 x double> %a to <32 x float>
+  store <32 x float> %b, <32 x float>* %out
+  ret void
+}
+
+attributes #0 = { nounwind "target-features"="+sve" }

From aa933d82f867ab4d33eafc5ee2666dbbc61d293d Mon Sep 17 00:00:00 2001
From: Raphael Isemann 
Date: Mon, 13 Jul 2020 13:14:55 +0200
Subject: [PATCH 085/771] [lldb][NFC] Early-exit in
 DWARFASTParserClang::ParseSingleMember

This patch just early-exits after the 'if (num_attributes > 0)' check.
---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  | 661 +++++++++---------
 1 file changed, 331 insertions(+), 330 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 929001671af7d..2d1db66e7fd91 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2360,393 +2360,394 @@ void DWARFASTParserClang::ParseSingleMember(
 
   DWARFAttributes attributes;
   const size_t num_attributes = die.GetAttributes(attributes);
-  if (num_attributes > 0) {
-    const char *name = nullptr;
-    const char *prop_name = nullptr;
-    const char *prop_getter_name = nullptr;
-    const char *prop_setter_name = nullptr;
-    uint32_t prop_attributes = 0;
-
-    bool is_artificial = false;
-    DWARFFormValue encoding_form;
-    AccessType accessibility = eAccessNone;
-    uint32_t member_byte_offset =
-        (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX;
-    llvm::Optional byte_size;
-    int64_t bit_offset = 0;
-    uint64_t data_bit_offset = UINT64_MAX;
-    size_t bit_size = 0;
-    bool is_external =
-        false; // On DW_TAG_members, this means the member is static
-    uint32_t i;
-    for (i = 0; i < num_attributes && !is_artificial; ++i) {
-      const dw_attr_t attr = attributes.AttributeAtIndex(i);
-      DWARFFormValue form_value;
-      if (attributes.ExtractFormValueAtIndex(i, form_value)) {
-        // DW_AT_data_member_location indicates the byte offset of the
-        // word from the base address of the structure.
-        //
-        // DW_AT_bit_offset indicates how many bits into the word
-        // (according to the host endianness) the low-order bit of the
-        // field starts.  AT_bit_offset can be negative.
-        //
-        // DW_AT_bit_size indicates the size of the field in bits.
-        switch (attr) {
-        case DW_AT_name:
-          name = form_value.AsCString();
-          break;
-        case DW_AT_type:
-          encoding_form = form_value;
-          break;
-        case DW_AT_bit_offset:
-          bit_offset = form_value.Signed();
-          break;
-        case DW_AT_bit_size:
-          bit_size = form_value.Unsigned();
-          break;
-        case DW_AT_byte_size:
-          byte_size = form_value.Unsigned();
-          break;
-        case DW_AT_data_bit_offset:
-          data_bit_offset = form_value.Unsigned();
-          break;
-        case DW_AT_data_member_location:
-          if (form_value.BlockData()) {
-            Value initialValue(0);
-            Value memberOffset(0);
-            const DWARFDataExtractor &debug_info_data = die.GetData();
-            uint32_t block_length = form_value.Unsigned();
-            uint32_t block_offset =
-                form_value.BlockData() - debug_info_data.GetDataStart();
-            if (DWARFExpression::Evaluate(
-                    nullptr, // ExecutionContext *
-                    nullptr, // RegisterContext *
-                    module_sp,
-                    DataExtractor(debug_info_data, block_offset, block_length),
-                    die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
-                    memberOffset, nullptr)) {
-              member_byte_offset = memberOffset.ResolveValue(nullptr).UInt();
-            }
-          } else {
-            // With DWARF 3 and later, if the value is an integer constant,
-            // this form value is the offset in bytes from the beginning of
-            // the containing entity.
-            member_byte_offset = form_value.Unsigned();
+  if (num_attributes == 0)
+    return;
+
+  const char *name = nullptr;
+  const char *prop_name = nullptr;
+  const char *prop_getter_name = nullptr;
+  const char *prop_setter_name = nullptr;
+  uint32_t prop_attributes = 0;
+
+  bool is_artificial = false;
+  DWARFFormValue encoding_form;
+  AccessType accessibility = eAccessNone;
+  uint32_t member_byte_offset =
+      (parent_die.Tag() == DW_TAG_union_type) ? 0 : UINT32_MAX;
+  llvm::Optional byte_size;
+  int64_t bit_offset = 0;
+  uint64_t data_bit_offset = UINT64_MAX;
+  size_t bit_size = 0;
+  bool is_external =
+      false; // On DW_TAG_members, this means the member is static
+  uint32_t i;
+  for (i = 0; i < num_attributes && !is_artificial; ++i) {
+    const dw_attr_t attr = attributes.AttributeAtIndex(i);
+    DWARFFormValue form_value;
+    if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+      // DW_AT_data_member_location indicates the byte offset of the
+      // word from the base address of the structure.
+      //
+      // DW_AT_bit_offset indicates how many bits into the word
+      // (according to the host endianness) the low-order bit of the
+      // field starts.  AT_bit_offset can be negative.
+      //
+      // DW_AT_bit_size indicates the size of the field in bits.
+      switch (attr) {
+      case DW_AT_name:
+        name = form_value.AsCString();
+        break;
+      case DW_AT_type:
+        encoding_form = form_value;
+        break;
+      case DW_AT_bit_offset:
+        bit_offset = form_value.Signed();
+        break;
+      case DW_AT_bit_size:
+        bit_size = form_value.Unsigned();
+        break;
+      case DW_AT_byte_size:
+        byte_size = form_value.Unsigned();
+        break;
+      case DW_AT_data_bit_offset:
+        data_bit_offset = form_value.Unsigned();
+        break;
+      case DW_AT_data_member_location:
+        if (form_value.BlockData()) {
+          Value initialValue(0);
+          Value memberOffset(0);
+          const DWARFDataExtractor &debug_info_data = die.GetData();
+          uint32_t block_length = form_value.Unsigned();
+          uint32_t block_offset =
+              form_value.BlockData() - debug_info_data.GetDataStart();
+          if (DWARFExpression::Evaluate(
+                  nullptr, // ExecutionContext *
+                  nullptr, // RegisterContext *
+                  module_sp,
+                  DataExtractor(debug_info_data, block_offset, block_length),
+                  die.GetCU(), eRegisterKindDWARF, &initialValue, nullptr,
+                  memberOffset, nullptr)) {
+            member_byte_offset = memberOffset.ResolveValue(nullptr).UInt();
           }
-          break;
+        } else {
+          // With DWARF 3 and later, if the value is an integer constant,
+          // this form value is the offset in bytes from the beginning of
+          // the containing entity.
+          member_byte_offset = form_value.Unsigned();
+        }
+        break;
 
-        case DW_AT_accessibility:
-          accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
-          break;
-        case DW_AT_artificial:
-          is_artificial = form_value.Boolean();
-          break;
-        case DW_AT_APPLE_property_name:
-          prop_name = form_value.AsCString();
-          break;
-        case DW_AT_APPLE_property_getter:
-          prop_getter_name = form_value.AsCString();
-          break;
-        case DW_AT_APPLE_property_setter:
-          prop_setter_name = form_value.AsCString();
-          break;
-        case DW_AT_APPLE_property_attribute:
-          prop_attributes = form_value.Unsigned();
-          break;
-        case DW_AT_external:
-          is_external = form_value.Boolean();
-          break;
+      case DW_AT_accessibility:
+        accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
+        break;
+      case DW_AT_artificial:
+        is_artificial = form_value.Boolean();
+        break;
+      case DW_AT_APPLE_property_name:
+        prop_name = form_value.AsCString();
+        break;
+      case DW_AT_APPLE_property_getter:
+        prop_getter_name = form_value.AsCString();
+        break;
+      case DW_AT_APPLE_property_setter:
+        prop_setter_name = form_value.AsCString();
+        break;
+      case DW_AT_APPLE_property_attribute:
+        prop_attributes = form_value.Unsigned();
+        break;
+      case DW_AT_external:
+        is_external = form_value.Boolean();
+        break;
 
-        default:
-        case DW_AT_declaration:
-        case DW_AT_description:
-        case DW_AT_mutable:
-        case DW_AT_visibility:
-        case DW_AT_sibling:
-          break;
-        }
+      default:
+      case DW_AT_declaration:
+      case DW_AT_description:
+      case DW_AT_mutable:
+      case DW_AT_visibility:
+      case DW_AT_sibling:
+        break;
       }
     }
+  }
 
-    if (prop_name) {
-      ConstString fixed_setter;
+  if (prop_name) {
+    ConstString fixed_setter;
 
-      // Check if the property getter/setter were provided as full names.
-      // We want basenames, so we extract them.
+    // Check if the property getter/setter were provided as full names.
+    // We want basenames, so we extract them.
 
-      if (prop_getter_name && prop_getter_name[0] == '-') {
-        ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
-        prop_getter_name = prop_getter_method.GetSelector().GetCString();
-      }
+    if (prop_getter_name && prop_getter_name[0] == '-') {
+      ObjCLanguage::MethodName prop_getter_method(prop_getter_name, true);
+      prop_getter_name = prop_getter_method.GetSelector().GetCString();
+    }
 
-      if (prop_setter_name && prop_setter_name[0] == '-') {
-        ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
-        prop_setter_name = prop_setter_method.GetSelector().GetCString();
-      }
+    if (prop_setter_name && prop_setter_name[0] == '-') {
+      ObjCLanguage::MethodName prop_setter_method(prop_setter_name, true);
+      prop_setter_name = prop_setter_method.GetSelector().GetCString();
+    }
 
-      // If the names haven't been provided, they need to be filled in.
+    // If the names haven't been provided, they need to be filled in.
 
-      if (!prop_getter_name) {
-        prop_getter_name = prop_name;
-      }
-      if (!prop_setter_name && prop_name[0] &&
-          !(prop_attributes & DW_APPLE_PROPERTY_readonly)) {
-        StreamString ss;
+    if (!prop_getter_name) {
+      prop_getter_name = prop_name;
+    }
+    if (!prop_setter_name && prop_name[0] &&
+        !(prop_attributes & DW_APPLE_PROPERTY_readonly)) {
+      StreamString ss;
 
-        ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);
+      ss.Printf("set%c%s:", toupper(prop_name[0]), &prop_name[1]);
 
-        fixed_setter.SetString(ss.GetString());
-        prop_setter_name = fixed_setter.GetCString();
-      }
+      fixed_setter.SetString(ss.GetString());
+      prop_setter_name = fixed_setter.GetCString();
     }
+  }
 
-    // Clang has a DWARF generation bug where sometimes it represents
-    // fields that are references with bad byte size and bit size/offset
-    // information such as:
-    //
-    //  DW_AT_byte_size( 0x00 )
-    //  DW_AT_bit_size( 0x40 )
-    //  DW_AT_bit_offset( 0xffffffffffffffc0 )
-    //
-    // So check the bit offset to make sure it is sane, and if the values
-    // are not sane, remove them. If we don't do this then we will end up
-    // with a crash if we try to use this type in an expression when clang
-    // becomes unhappy with its recycled debug info.
+  // Clang has a DWARF generation bug where sometimes it represents
+  // fields that are references with bad byte size and bit size/offset
+  // information such as:
+  //
+  //  DW_AT_byte_size( 0x00 )
+  //  DW_AT_bit_size( 0x40 )
+  //  DW_AT_bit_offset( 0xffffffffffffffc0 )
+  //
+  // So check the bit offset to make sure it is sane, and if the values
+  // are not sane, remove them. If we don't do this then we will end up
+  // with a crash if we try to use this type in an expression when clang
+  // becomes unhappy with its recycled debug info.
 
-    if (byte_size.getValueOr(0) == 0 && bit_offset < 0) {
-      bit_size = 0;
-      bit_offset = 0;
-    }
+  if (byte_size.getValueOr(0) == 0 && bit_offset < 0) {
+    bit_size = 0;
+    bit_offset = 0;
+  }
 
-    const bool class_is_objc_object_or_interface =
-        TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type);
+  const bool class_is_objc_object_or_interface =
+      TypeSystemClang::IsObjCObjectOrInterfaceType(class_clang_type);
 
-    // FIXME: Make Clang ignore Objective-C accessibility for expressions
-    if (class_is_objc_object_or_interface)
-      accessibility = eAccessNone;
+  // FIXME: Make Clang ignore Objective-C accessibility for expressions
+  if (class_is_objc_object_or_interface)
+    accessibility = eAccessNone;
 
-    // Handle static members
-    if (is_external && member_byte_offset == UINT32_MAX) {
-      Type *var_type = die.ResolveTypeUID(encoding_form.Reference());
+  // Handle static members
+  if (is_external && member_byte_offset == UINT32_MAX) {
+    Type *var_type = die.ResolveTypeUID(encoding_form.Reference());
 
-      if (var_type) {
-        if (accessibility == eAccessNone)
-          accessibility = eAccessPublic;
-        TypeSystemClang::AddVariableToRecordType(
-            class_clang_type, name, var_type->GetLayoutCompilerType(),
-            accessibility);
-      }
-      return;
+    if (var_type) {
+      if (accessibility == eAccessNone)
+        accessibility = eAccessPublic;
+      TypeSystemClang::AddVariableToRecordType(
+          class_clang_type, name, var_type->GetLayoutCompilerType(),
+          accessibility);
     }
+    return;
+  }
 
-    if (!is_artificial) {
-      Type *member_type = die.ResolveTypeUID(encoding_form.Reference());
-
-      clang::FieldDecl *field_decl = nullptr;
-      const uint64_t character_width = 8;
-      const uint64_t word_width = 32;
-      if (tag == DW_TAG_member) {
-        if (member_type) {
-          CompilerType member_clang_type = member_type->GetLayoutCompilerType();
+  if (!is_artificial) {
+    Type *member_type = die.ResolveTypeUID(encoding_form.Reference());
 
-          if (accessibility == eAccessNone)
-            accessibility = default_accessibility;
-          member_accessibilities.push_back(accessibility);
+    clang::FieldDecl *field_decl = nullptr;
+    const uint64_t character_width = 8;
+    const uint64_t word_width = 32;
+    if (tag == DW_TAG_member) {
+      if (member_type) {
+        CompilerType member_clang_type = member_type->GetLayoutCompilerType();
 
-          uint64_t field_bit_offset =
-              (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+        if (accessibility == eAccessNone)
+          accessibility = default_accessibility;
+        member_accessibilities.push_back(accessibility);
 
-          if (bit_size > 0) {
-            FieldInfo this_field_info;
-            this_field_info.bit_offset = field_bit_offset;
-            this_field_info.bit_size = bit_size;
+        uint64_t field_bit_offset =
+            (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
 
-            if (data_bit_offset != UINT64_MAX) {
-              this_field_info.bit_offset = data_bit_offset;
-            } else {
-              if (!byte_size)
-                byte_size = member_type->GetByteSize();
+        if (bit_size > 0) {
+          FieldInfo this_field_info;
+          this_field_info.bit_offset = field_bit_offset;
+          this_field_info.bit_size = bit_size;
 
-              ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
-              if (objfile->GetByteOrder() == eByteOrderLittle) {
-                this_field_info.bit_offset += byte_size.getValueOr(0) * 8;
-                this_field_info.bit_offset -= (bit_offset + bit_size);
-              } else {
-                this_field_info.bit_offset += bit_offset;
-              }
-            }
+          if (data_bit_offset != UINT64_MAX) {
+            this_field_info.bit_offset = data_bit_offset;
+          } else {
+            if (!byte_size)
+              byte_size = member_type->GetByteSize();
 
-            if ((this_field_info.bit_offset >= parent_bit_size) ||
-                (last_field_info.IsBitfield() &&
-                 !last_field_info.NextBitfieldOffsetIsValid(
-                     this_field_info.bit_offset))) {
-              ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
-              objfile->GetModule()->ReportWarning(
-                  "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
-                  "bit offset (0x%8.8" PRIx64
-                  ") member will be ignored. Please file a bug against the "
-                  "compiler and include the preprocessed output for %s\n",
-                  die.GetID(), DW_TAG_value_to_name(tag), name,
-                  this_field_info.bit_offset, GetUnitName(parent_die).c_str());
-              return;
+            ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
+            if (objfile->GetByteOrder() == eByteOrderLittle) {
+              this_field_info.bit_offset += byte_size.getValueOr(0) * 8;
+              this_field_info.bit_offset -= (bit_offset + bit_size);
+            } else {
+              this_field_info.bit_offset += bit_offset;
             }
+          }
 
-            // Update the field bit offset we will report for layout
-            field_bit_offset = this_field_info.bit_offset;
-
-            // Objective-C has invalid DW_AT_bit_offset values in older
-            // versions of clang, so we have to be careful and only insert
-            // unnamed bitfields if we have a new enough clang.
-            bool detect_unnamed_bitfields = true;
+          if ((this_field_info.bit_offset >= parent_bit_size) ||
+              (last_field_info.IsBitfield() &&
+               !last_field_info.NextBitfieldOffsetIsValid(
+                   this_field_info.bit_offset))) {
+            ObjectFile *objfile = die.GetDWARF()->GetObjectFile();
+            objfile->GetModule()->ReportWarning(
+                "0x%8.8" PRIx64 ": %s bitfield named \"%s\" has invalid "
+                "bit offset (0x%8.8" PRIx64
+                ") member will be ignored. Please file a bug against the "
+                "compiler and include the preprocessed output for %s\n",
+                die.GetID(), DW_TAG_value_to_name(tag), name,
+                this_field_info.bit_offset, GetUnitName(parent_die).c_str());
+            return;
+          }
 
-            if (class_is_objc_object_or_interface)
-              detect_unnamed_bitfields =
-                  die.GetCU()->Supports_unnamed_objc_bitfields();
+          // Update the field bit offset we will report for layout
+          field_bit_offset = this_field_info.bit_offset;
 
-            if (detect_unnamed_bitfields) {
-              clang::Optional unnamed_field_info;
-              uint64_t last_field_end = 0;
+          // Objective-C has invalid DW_AT_bit_offset values in older
+          // versions of clang, so we have to be careful and only insert
+          // unnamed bitfields if we have a new enough clang.
+          bool detect_unnamed_bitfields = true;
 
-              last_field_end =
-                  last_field_info.bit_offset + last_field_info.bit_size;
+          if (class_is_objc_object_or_interface)
+            detect_unnamed_bitfields =
+                die.GetCU()->Supports_unnamed_objc_bitfields();
 
-              if (!last_field_info.IsBitfield()) {
-                // The last field was not a bit-field...
-                // but if it did take up the entire word then we need to extend
-                // last_field_end so the bit-field does not step into the last
-                // fields padding.
-                if (last_field_end != 0 && ((last_field_end % word_width) != 0))
-                  last_field_end += word_width - (last_field_end % word_width);
-              }
+          if (detect_unnamed_bitfields) {
+            clang::Optional unnamed_field_info;
+            uint64_t last_field_end = 0;
 
-              // If we have a gap between the last_field_end and the current
-              // field we have an unnamed bit-field.
-              // If we have a base class, we assume there is no unnamed
-              // bit-field if this is the first field since the gap can be
-              // attributed to the members from the base class. This assumption
-              // is not correct if the first field of the derived class is
-              // indeed an unnamed bit-field. We currently do not have the
-              // machinary to track the offset of the last field of classes we
-              // have seen before, so we are not handling this case.
-              if (this_field_info.bit_offset != last_field_end &&
-                  this_field_info.bit_offset > last_field_end &&
-                  !(last_field_info.bit_offset == 0 &&
-                    last_field_info.bit_size == 0 &&
-                    layout_info.base_offsets.size() != 0)) {
-                unnamed_field_info = FieldInfo{};
-                unnamed_field_info->bit_size =
-                    this_field_info.bit_offset - last_field_end;
-                unnamed_field_info->bit_offset = last_field_end;
-              }
+            last_field_end =
+                last_field_info.bit_offset + last_field_info.bit_size;
 
-              if (unnamed_field_info) {
-                clang::FieldDecl *unnamed_bitfield_decl =
-                    TypeSystemClang::AddFieldToRecordType(
-                        class_clang_type, llvm::StringRef(),
-                        m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,
-                                                                  word_width),
-                        accessibility, unnamed_field_info->bit_size);
+            if (!last_field_info.IsBitfield()) {
+              // The last field was not a bit-field...
+              // but if it did take up the entire word then we need to extend
+              // last_field_end so the bit-field does not step into the last
+              // fields padding.
+              if (last_field_end != 0 && ((last_field_end % word_width) != 0))
+                last_field_end += word_width - (last_field_end % word_width);
+            }
 
-                layout_info.field_offsets.insert(std::make_pair(
-                    unnamed_bitfield_decl, unnamed_field_info->bit_offset));
-              }
+            // If we have a gap between the last_field_end and the current
+            // field we have an unnamed bit-field.
+            // If we have a base class, we assume there is no unnamed
+            // bit-field if this is the first field since the gap can be
+            // attributed to the members from the base class. This assumption
+            // is not correct if the first field of the derived class is
+            // indeed an unnamed bit-field. We currently do not have the
+            // machinary to track the offset of the last field of classes we
+            // have seen before, so we are not handling this case.
+            if (this_field_info.bit_offset != last_field_end &&
+                this_field_info.bit_offset > last_field_end &&
+                !(last_field_info.bit_offset == 0 &&
+                  last_field_info.bit_size == 0 &&
+                  layout_info.base_offsets.size() != 0)) {
+              unnamed_field_info = FieldInfo{};
+              unnamed_field_info->bit_size =
+                  this_field_info.bit_offset - last_field_end;
+              unnamed_field_info->bit_offset = last_field_end;
             }
 
-            last_field_info = this_field_info;
-            last_field_info.SetIsBitfield(true);
-          } else {
-            last_field_info.bit_offset = field_bit_offset;
+            if (unnamed_field_info) {
+              clang::FieldDecl *unnamed_bitfield_decl =
+                  TypeSystemClang::AddFieldToRecordType(
+                      class_clang_type, llvm::StringRef(),
+                      m_ast.GetBuiltinTypeForEncodingAndBitSize(eEncodingSint,
+                                                                word_width),
+                      accessibility, unnamed_field_info->bit_size);
 
-            if (llvm::Optional clang_type_size =
-                    member_clang_type.GetByteSize(nullptr)) {
-              last_field_info.bit_size = *clang_type_size * character_width;
+              layout_info.field_offsets.insert(std::make_pair(
+                  unnamed_bitfield_decl, unnamed_field_info->bit_offset));
             }
+          }
 
-            last_field_info.SetIsBitfield(false);
+          last_field_info = this_field_info;
+          last_field_info.SetIsBitfield(true);
+        } else {
+          last_field_info.bit_offset = field_bit_offset;
+
+          if (llvm::Optional clang_type_size =
+                  member_clang_type.GetByteSize(nullptr)) {
+            last_field_info.bit_size = *clang_type_size * character_width;
           }
 
-          if (!member_clang_type.IsCompleteType())
-            member_clang_type.GetCompleteType();
-
-          {
-            // Older versions of clang emit array[0] and array[1] in the
-            // same way (). If the current field
-            // is at the end of the structure, then there is definitely no
-            // room for extra elements and we override the type to
-            // array[0].
-
-            CompilerType member_array_element_type;
-            uint64_t member_array_size;
-            bool member_array_is_incomplete;
-
-            if (member_clang_type.IsArrayType(&member_array_element_type,
-                                              &member_array_size,
-                                              &member_array_is_incomplete) &&
-                !member_array_is_incomplete) {
-              uint64_t parent_byte_size =
-                  parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size,
-                                                         UINT64_MAX);
-
-              if (member_byte_offset >= parent_byte_size) {
-                if (member_array_size != 1 &&
-                    (member_array_size != 0 ||
-                     member_byte_offset > parent_byte_size)) {
-                  module_sp->ReportError(
-                      "0x%8.8" PRIx64
-                      ": DW_TAG_member '%s' refers to type 0x%8.8x"
-                      " which extends beyond the bounds of 0x%8.8" PRIx64,
-                      die.GetID(), name, encoding_form.Reference().GetOffset(),
-                      parent_die.GetID());
-                }
+          last_field_info.SetIsBitfield(false);
+        }
 
-                member_clang_type =
-                    m_ast.CreateArrayType(member_array_element_type, 0, false);
+        if (!member_clang_type.IsCompleteType())
+          member_clang_type.GetCompleteType();
+
+        {
+          // Older versions of clang emit array[0] and array[1] in the
+          // same way (). If the current field
+          // is at the end of the structure, then there is definitely no
+          // room for extra elements and we override the type to
+          // array[0].
+
+          CompilerType member_array_element_type;
+          uint64_t member_array_size;
+          bool member_array_is_incomplete;
+
+          if (member_clang_type.IsArrayType(&member_array_element_type,
+                                            &member_array_size,
+                                            &member_array_is_incomplete) &&
+              !member_array_is_incomplete) {
+            uint64_t parent_byte_size =
+                parent_die.GetAttributeValueAsUnsigned(DW_AT_byte_size,
+                                                       UINT64_MAX);
+
+            if (member_byte_offset >= parent_byte_size) {
+              if (member_array_size != 1 &&
+                  (member_array_size != 0 ||
+                   member_byte_offset > parent_byte_size)) {
+                module_sp->ReportError(
+                    "0x%8.8" PRIx64
+                    ": DW_TAG_member '%s' refers to type 0x%8.8x"
+                    " which extends beyond the bounds of 0x%8.8" PRIx64,
+                    die.GetID(), name, encoding_form.Reference().GetOffset(),
+                    parent_die.GetID());
               }
+
+              member_clang_type =
+                  m_ast.CreateArrayType(member_array_element_type, 0, false);
             }
           }
+        }
 
-          CompleteType(member_clang_type);
+        CompleteType(member_clang_type);
 
-          field_decl = TypeSystemClang::AddFieldToRecordType(
-              class_clang_type, name, member_clang_type, accessibility,
-              bit_size);
+        field_decl = TypeSystemClang::AddFieldToRecordType(
+            class_clang_type, name, member_clang_type, accessibility,
+            bit_size);
 
-          m_ast.SetMetadataAsUserID(field_decl, die.GetID());
+        m_ast.SetMetadataAsUserID(field_decl, die.GetID());
 
-          layout_info.field_offsets.insert(
-              std::make_pair(field_decl, field_bit_offset));
-        } else {
-          if (name)
-            module_sp->ReportError(
-                "0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8x"
-                " which was unable to be parsed",
-                die.GetID(), name, encoding_form.Reference().GetOffset());
-          else
-            module_sp->ReportError(
-                "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x"
-                " which was unable to be parsed",
-                die.GetID(), encoding_form.Reference().GetOffset());
-        }
+        layout_info.field_offsets.insert(
+            std::make_pair(field_decl, field_bit_offset));
+      } else {
+        if (name)
+          module_sp->ReportError(
+              "0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8x"
+              " which was unable to be parsed",
+              die.GetID(), name, encoding_form.Reference().GetOffset());
+        else
+          module_sp->ReportError(
+              "0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8x"
+              " which was unable to be parsed",
+              die.GetID(), encoding_form.Reference().GetOffset());
       }
+    }
 
-      if (prop_name != nullptr && member_type) {
-        clang::ObjCIvarDecl *ivar_decl = nullptr;
+    if (prop_name != nullptr && member_type) {
+      clang::ObjCIvarDecl *ivar_decl = nullptr;
 
-        if (field_decl) {
-          ivar_decl = clang::dyn_cast(field_decl);
-          assert(ivar_decl != nullptr);
-        }
+      if (field_decl) {
+        ivar_decl = clang::dyn_cast(field_decl);
+        assert(ivar_decl != nullptr);
+      }
 
-        ClangASTMetadata metadata;
-        metadata.SetUserID(die.GetID());
-        delayed_properties.push_back(DelayedAddObjCClassProperty(
-            class_clang_type, prop_name, member_type->GetLayoutCompilerType(),
-            ivar_decl, prop_setter_name, prop_getter_name, prop_attributes,
-            &metadata));
+      ClangASTMetadata metadata;
+      metadata.SetUserID(die.GetID());
+      delayed_properties.push_back(DelayedAddObjCClassProperty(
+          class_clang_type, prop_name, member_type->GetLayoutCompilerType(),
+          ivar_decl, prop_setter_name, prop_getter_name, prop_attributes,
+          &metadata));
 
-        if (ivar_decl)
-          m_ast.SetMetadataAsUserID(ivar_decl, die.GetID());
-      }
+      if (ivar_decl)
+        m_ast.SetMetadataAsUserID(ivar_decl, die.GetID());
     }
   }
 }

From 84a170178c4431b7536c83ff0e5ce80774d08df6 Mon Sep 17 00:00:00 2001
From: Georgii Rymar 
Date: Wed, 8 Jul 2020 14:54:45 +0300
Subject: [PATCH 086/771] [llvm-readobj] - Add a generic test for
 --dyn-relocations and fix an issue.

We have an issue currently: --dyn-relocations always prints the following
relocation header when dumping `DynPLTRelRegion`:

"Offset  Info  Type Symbol's Value  Symbol's Name + Addend"

I.e. even for an empty object, --dyn-relocations still prints this.
It is a easy to fix bug, but we have no dedicated test case for this option.
(we have a dynamic-reloc-no-section-headers.test, which has a slightly different purpose).

This patch adds a test and fixes the behavior.

Differential revision: https://reviews.llvm.org/D83387
---
 .../tools/llvm-readobj/ELF/dynamic-reloc.test | 135 ++++++++++++++++++
 llvm/tools/llvm-readobj/ELFDumper.cpp         |  27 ++--
 2 files changed, 149 insertions(+), 13 deletions(-)
 create mode 100644 llvm/test/tools/llvm-readobj/ELF/dynamic-reloc.test

diff --git a/llvm/test/tools/llvm-readobj/ELF/dynamic-reloc.test b/llvm/test/tools/llvm-readobj/ELF/dynamic-reloc.test
new file mode 100644
index 0000000000000..79faebadb40a4
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/dynamic-reloc.test
@@ -0,0 +1,135 @@
+## Test that we are able to print dynamic relocations with --dyn-relocations.
+
+## Check what we print when there are no dynamic relocations in an object.
+# RUN: yaml2obj --docnum=1 %s -o %t1
+# RUN: llvm-readobj --dyn-relocations %t1 2>&1 | FileCheck %s --check-prefix=LLVM-NONE
+# RUN: llvm-readelf --dyn-relocations %t1 2>&1 | FileCheck %s --implicit-check-not={{.}} --allow-empty
+
+# LLVM-NONE:      Dynamic Relocations {
+# LLVM-NONE-NEXT: }
+# LLVM-NONE-NOT:  {{.}}
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+
+## Check that we dump all possbile dynamic relocation sections.
+# RUN: yaml2obj --docnum=2 %s -o %t2.1
+# RUN: llvm-readobj --dyn-relocations %t2.1 2>&1 | \
+# RUN:   FileCheck %s --implicit-check-not=warning: --check-prefix=LLVM-RELOCS
+# RUN: llvm-readelf --dyn-relocations %t2.1 2>&1 | \
+# RUN:   FileCheck %s --implicit-check-not=warning: --strict-whitespace \
+# RUN:     --match-full-lines --check-prefixes=GNU-RELOCS,GNU-PLTREL
+
+## 7 == DT_RELA.
+# RUN: yaml2obj --docnum=2 %s -DDTPLTREL=7 -DPLTTYPE=SHT_RELA -DPLTRELSZ=0x18 -o %t2.2
+# RUN: llvm-readobj --dyn-relocations %t2.2 2>&1 | \
+# RUN:   FileCheck %s --implicit-check-not=warning: --check-prefix=LLVM-RELOCS
+# RUN: llvm-readelf --dyn-relocations %t2.2 2>&1 | \
+# RUN:   FileCheck %s --implicit-check-not=warning: --strict-whitespace \
+# RUN:     --match-full-lines --check-prefixes=GNU-RELOCS,GNU-PLTRELA
+
+# LLVM-RELOCS:      Dynamic Relocations {
+# LLVM-RELOCS-NEXT:   0x1 R_X86_64_NONE foo 0x0
+# LLVM-RELOCS-NEXT:   0x2 R_X86_64_NONE foo 0x0
+# LLVM-RELOCS-NEXT:   0x4 R_X86_64_RELATIVE - 0x0
+# LLVM-RELOCS-NEXT:   0x8 R_X86_64_NONE foo 0x0
+# LLVM-RELOCS-NEXT: }
+
+#       GNU-RELOCS:'RELA' relocation section at offset 0x78 contains 24 bytes:
+#  GNU-RELOCS-NEXT:    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
+#  GNU-RELOCS-NEXT:0000000000000001  0000000100000000 R_X86_64_NONE          0000000000000000 foo + 0
+# GNU-RELOCS-EMPTY:
+#  GNU-RELOCS-NEXT:'REL' relocation section at offset 0x90 contains 16 bytes:
+#  GNU-RELOCS-NEXT:    Offset             Info             Type               Symbol's Value  Symbol's Name
+#  GNU-RELOCS-NEXT:0000000000000002  0000000100000000 R_X86_64_NONE          0000000000000000 foo
+# GNU-RELOCS-EMPTY:
+#  GNU-RELOCS-NEXT:'RELR' relocation section at offset 0xa0 contains 8 bytes:
+#  GNU-RELOCS-NEXT:    Offset             Info             Type               Symbol's Value  Symbol's Name
+#  GNU-RELOCS-NEXT:0000000000000004  0000000000000008 R_X86_64_RELATIVE                 {{$}}
+# GNU-RELOCS-EMPTY:
+#  GNU-PLTREL-NEXT:'PLT' relocation section at offset 0xa8 contains 16 bytes:
+#  GNU-PLTREL-NEXT:    Offset             Info             Type               Symbol's Value  Symbol's Name
+#  GNU-PLTREL-NEXT:0000000000000008  0000000100000000 R_X86_64_NONE          0000000000000000 foo
+# GNU-PLTRELA-NEXT:'PLT' relocation section at offset 0xa8 contains 24 bytes:
+# GNU-PLTRELA-NEXT:    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
+# GNU-PLTRELA-NEXT:0000000000000008  0000000100000000 R_X86_64_NONE          0000000000000000 foo + 0
+# GNU-RELOCS-EMPTY:
+#   GNU-RELOCS-NOT:{{.}}
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_DYN
+  Machine: EM_X86_64
+Sections:
+  - Name: .rela.dyn
+    Type: SHT_RELA
+    Relocations:
+      - Type:   R_X86_64_NONE
+        Offset: 0x1
+        Symbol: foo
+  - Name: .rel.dyn
+    Type: SHT_REL
+    Relocations:
+      - Type:   R_X86_64_NONE
+        Offset: 0x2
+        Symbol: foo
+  - Name:    .relr.dyn
+    Type:    SHT_RELR
+    Flags:   [ SHF_ALLOC ]
+    Entries: [ 0x0000000000000004 ]
+  - Name:    .plt
+    Type:    [[PLTTYPE=SHT_REL]]
+    Relocations:
+      - Type:   R_X86_64_NONE
+        Offset: 0x8
+        Symbol: foo
+  - Name: .dynamic
+    Type: SHT_DYNAMIC
+    Entries:
+      - Tag:   DT_RELA
+        Value: 0x0
+      - Tag:   DT_RELASZ
+        Value: 0x18
+      - Tag:   DT_RELAENT
+        Value: 0x18
+## 0x18 == offset of .rel.dyn in the segment.
+      - Tag:   DT_REL
+        Value: 0x18
+      - Tag:   DT_RELSZ
+        Value: 0x10
+      - Tag:   DT_RELENT
+        Value: 0x10
+## 0x28 == offset of .relr.dyn section in the segment.
+      - Tag:   DT_RELR
+        Value: 0x28
+      - Tag:   DT_RELRSZ
+        Value: 0x8
+      - Tag:   DT_RELRENT
+        Value: 0x8
+## 0x30 == offset of .plt section in the segment.
+      - Tag:   DT_JMPREL
+        Value: 0x30
+      - Tag:   DT_PLTREL
+        Value: [[DTPLTREL=17]] ## 17 == DT_REL
+      - Tag:   DT_PLTRELSZ
+        Value: [[PLTRELSZ=0x10]]
+      - Tag:   DT_NULL
+        Value: 0x0
+Symbols:
+  - Name: foo
+DynamicSymbols:
+  - Name: foo
+ProgramHeaders:
+  - Type:  PT_LOAD
+    Sections:
+      - Section: .rela.dyn
+      - Section: .rel.dyn
+      - Section: .relr.dyn
+      - Section: .plt
+      - Section: .dynamic
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 6a7f37e39a9ab..56528d321de67 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -4568,19 +4568,20 @@ void GNUStyle::printDynamicRelocations(const ELFO *Obj) {
                          Obj->base(),
                      1)
        << " contains " << DynPLTRelRegion.Size << " bytes:\n";
-  }
-  if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) {
-    printRelocHeader(ELF::SHT_RELA);
-    for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef())
-      printDynamicRelocation(Obj, Rela, true);
-  } else {
-    printRelocHeader(ELF::SHT_REL);
-    for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef()) {
-      Elf_Rela Rela;
-      Rela.r_offset = Rel.r_offset;
-      Rela.r_info = Rel.r_info;
-      Rela.r_addend = 0;
-      printDynamicRelocation(Obj, Rela, false);
+
+    if (DynPLTRelRegion.EntSize == sizeof(Elf_Rela)) {
+      printRelocHeader(ELF::SHT_RELA);
+      for (const Elf_Rela &Rela : DynPLTRelRegion.getAsArrayRef())
+        printDynamicRelocation(Obj, Rela, true);
+    } else {
+      printRelocHeader(ELF::SHT_REL);
+      for (const Elf_Rel &Rel : DynPLTRelRegion.getAsArrayRef()) {
+        Elf_Rela Rela;
+        Rela.r_offset = Rel.r_offset;
+        Rela.r_info = Rel.r_info;
+        Rela.r_addend = 0;
+        printDynamicRelocation(Obj, Rela, false);
+      }
     }
   }
 }

From 38998cfa9c1e887636a7ca7278b71fde5b19dd0e Mon Sep 17 00:00:00 2001
From: Mirko Brkusanin 
Date: Mon, 13 Jul 2020 13:35:34 +0200
Subject: [PATCH 087/771] [AMDGPU][GlobalISel] Fix subregister index for EXEC
 register in selectBallot.

Temporarily remove subregister for EXEC in selectBallot added in
https://reviews.llvm.org/D83214 to fix failures on expensive checks buildbot.
---
 llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp         | 4 +---
 .../test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll | 2 +-
 .../test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll | 5 +++--
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index 84734365cc658..2025c0fa5d21b 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -1061,9 +1061,7 @@ bool AMDGPUInstructionSelector::selectBallot(MachineInstr &I) const {
       BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg).addImm(0);
     } else if (Value == -1) { // all ones
       Register SrcReg = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;
-      const unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;
-      BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), DstReg)
-          .addReg(SrcReg, 0, SubReg);
+      BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), DstReg).addReg(SrcReg);
     } else
       return false;
   } else {
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
index b15fbf64fd8e2..6627804bdf76a 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i32.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -march=amdgcn -mcpu=gfx1010 -mattr=+wavefrontsize32,-wavefrontsize64 -global-isel < %s | FileCheck %s
+; RUN: llc -march=amdgcn -mcpu=gfx1010 -mattr=+wavefrontsize32,-wavefrontsize64 -global-isel -verify-machineinstrs < %s | FileCheck %s
 
 declare i32 @llvm.amdgcn.ballot.i32(i1)
 
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll
index fcea5f8c9c59e..5f5af2954ff56 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ballot.i64.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -march=amdgcn -mcpu=gfx900 -global-isel < %s | FileCheck %s
+; RUN: llc -march=amdgcn -mcpu=gfx900 -global-isel -verify-machineinstrs < %s | FileCheck %s
 
 declare i64 @llvm.amdgcn.ballot.i64(i1)
 
@@ -20,7 +20,8 @@ define amdgpu_cs i64 @constant_false() {
 define amdgpu_cs i64 @constant_true() {
 ; CHECK-LABEL: constant_true:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_mov_b64 s[0:1], exec
+; CHECK-NEXT:    s_mov_b32 s0, exec_lo
+; CHECK-NEXT:    s_mov_b32 s1, exec_hi
 ; CHECK-NEXT:    ; return to shader part epilog
   %ballot = call i64 @llvm.amdgcn.ballot.i64(i1 1)
   ret i64 %ballot

From e73d0b5719966ddbeff7a3da70a3cb782c3733ed Mon Sep 17 00:00:00 2001
From: Hans Wennborg 
Date: Thu, 9 Jul 2020 14:54:53 +0200
Subject: [PATCH 088/771] [COFF] Error on unexpected .pdata size

Previously, lld would crash if the .pdata size was not an even multiple
of the expected .pdata entry size. This makes it error gracefully instead.

(We hit this in Chromium due to an assembler problem: https://crbug.com/1101577)

Differential revision: https://reviews.llvm.org/D83479
---
 lld/COFF/Writer.cpp                |  8 +++
 lld/test/COFF/pdata-arm64-bad.yaml | 89 ++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+)
 create mode 100644 lld/test/COFF/pdata-arm64-bad.yaml

diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index ffa0a0006f0ed..3bcc1777f7ac8 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1864,6 +1864,10 @@ void Writer::sortExceptionTable() {
   uint8_t *end = bufAddr(lastPdata) + lastPdata->getSize();
   if (config->machine == AMD64) {
     struct Entry { ulittle32_t begin, end, unwind; };
+    if ((end - begin) % sizeof(Entry) != 0) {
+      fatal("unexpected .pdata size: " + Twine(end - begin) +
+            " is not a multiple of " + Twine(sizeof(Entry)));
+    }
     parallelSort(
         MutableArrayRef((Entry *)begin, (Entry *)end),
         [](const Entry &a, const Entry &b) { return a.begin < b.begin; });
@@ -1871,6 +1875,10 @@ void Writer::sortExceptionTable() {
   }
   if (config->machine == ARMNT || config->machine == ARM64) {
     struct Entry { ulittle32_t begin, unwind; };
+    if ((end - begin) % sizeof(Entry) != 0) {
+      fatal("unexpected .pdata size: " + Twine(end - begin) +
+            " is not a multiple of " + Twine(sizeof(Entry)));
+    }
     parallelSort(
         MutableArrayRef((Entry *)begin, (Entry *)end),
         [](const Entry &a, const Entry &b) { return a.begin < b.begin; });
diff --git a/lld/test/COFF/pdata-arm64-bad.yaml b/lld/test/COFF/pdata-arm64-bad.yaml
new file mode 100644
index 0000000000000..d6b4967457952
--- /dev/null
+++ b/lld/test/COFF/pdata-arm64-bad.yaml
@@ -0,0 +1,89 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: not lld-link /out:%t.exe /entry:func1 /subsystem:console %t.obj 2>&1 | FileCheck %s
+
+# This file is like pdata-arm64.yaml, except that .pdata has been extended with
+# 4 bytes. This can happen due to for example bad assembler input. Check that
+# lld errors gracefully instead of crashing.
+
+# CHECK: unexpected .pdata size: 20 is not a multiple of 8
+
+--- !COFF
+header:
+  Machine:         IMAGE_FILE_MACHINE_ARM64
+  Characteristics: [  ]
+sections:
+  - Name:            .text
+    Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     ff4300d1f37b00a9f303012a00000094e003132a00000094f37b40a9ff430091c0035fd6f353bea9fe0b00f9f303012af403022a00000094e003132a00000094e003142a00000094fe0b40f9f353c2a8c0035fd6c0035fd6
+    Relocations:
+      - VirtualAddress:  12
+        SymbolName:      func3
+        Type:            IMAGE_REL_ARM64_BRANCH26
+      - VirtualAddress:  20
+        SymbolName:      func3
+        Type:            IMAGE_REL_ARM64_BRANCH26
+      - VirtualAddress:  52
+        SymbolName:      func3
+        Type:            IMAGE_REL_ARM64_BRANCH26
+      - VirtualAddress:  60
+        SymbolName:      func3
+        Type:            IMAGE_REL_ARM64_BRANCH26
+      - VirtualAddress:  68
+        SymbolName:      func3
+        Type:            IMAGE_REL_ARM64_BRANCH26
+  - Name:            .pdata
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+    Alignment:       4
+    SectionData:     0000000031002201000000002500a10000000000
+    Relocations:
+      - VirtualAddress:  0
+        SymbolName:      func2
+        Type:            IMAGE_REL_ARM64_ADDR32NB
+      - VirtualAddress:  8
+        SymbolName:      func1
+        Type:            IMAGE_REL_ARM64_ADDR32NB
+symbols:
+  - Name:            .text
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          57
+      NumberOfRelocations: 0
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          1
+  - Name:            .pdata
+    Value:           0
+    SectionNumber:   2
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_STATIC
+    SectionDefinition:
+      Length:          20
+      NumberOfRelocations: 2
+      NumberOfLinenumbers: 0
+      CheckSum:        0
+      Number:          2
+  - Name:            func1
+    Value:           0
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            func2
+    Value:           36
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_FUNCTION
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+  - Name:            func3
+    Value:           84
+    SectionNumber:   1
+    SimpleType:      IMAGE_SYM_TYPE_NULL
+    ComplexType:     IMAGE_SYM_DTYPE_NULL
+    StorageClass:    IMAGE_SYM_CLASS_EXTERNAL
+...

From fbb6c9df28ccc8c35d39ea56707f71a3b2619071 Mon Sep 17 00:00:00 2001
From: Georgii Rymar 
Date: Mon, 13 Jul 2020 15:14:06 +0300
Subject: [PATCH 089/771] [LLD][ELF] - Fix the test after llvm-readelf output
 change.

An issue for llvm-readelf was fixed in
https://reviews.llvm.org/rG84a170178c4431b7536c83ff0e5ce80774d08df6

Now it produce no output for this test.
---
 lld/test/ELF/ppc64-rel-so-local-calls.s | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/lld/test/ELF/ppc64-rel-so-local-calls.s b/lld/test/ELF/ppc64-rel-so-local-calls.s
index 2bc89d554a022..3d2e0673c3a74 100644
--- a/lld/test/ELF/ppc64-rel-so-local-calls.s
+++ b/lld/test/ELF/ppc64-rel-so-local-calls.s
@@ -2,15 +2,11 @@
 
 // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
 // RUN: ld.lld -shared %t.o -o %t.so
-// RUN: llvm-readelf -dyn-relocations %t.so | FileCheck %s
+// RUN: llvm-readelf -dyn-relocations %t.so | FileCheck %s -allow-empty --implicit-check-not={{.}}
 
 // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
 // RUN: ld.lld -shared %t.o -o %t.so
-// RUN: llvm-readelf -dyn-relocations %t.so | FileCheck %s
-
-
-// CHECK-NOT: foo
-// CHECK-NOT: bar
+// RUN: llvm-readelf -dyn-relocations %t.so | FileCheck %s -allow-empty --implicit-check-not={{.}}
 
 	.text
 	.abiversion 2

From d96a47c61625f853ec42a151ae3783e30a3943f3 Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Mon, 13 Jul 2020 14:29:47 +0200
Subject: [PATCH 090/771] [analyzer] ctu-on-demand-parsing tests: replace linux
 -> system-linux

Differential Revision: https://reviews.llvm.org/D83555
---
 clang/test/Analysis/ctu-on-demand-parsing.c   | 2 +-
 clang/test/Analysis/ctu-on-demand-parsing.cpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/Analysis/ctu-on-demand-parsing.c b/clang/test/Analysis/ctu-on-demand-parsing.c
index 5adce7f369639..07a72a1046467 100644
--- a/clang/test/Analysis/ctu-on-demand-parsing.c
+++ b/clang/test/Analysis/ctu-on-demand-parsing.c
@@ -19,7 +19,7 @@
 // RUN:   -verify ctu-on-demand-parsing.c
 //
 // FIXME: Path handling should work on all platforms.
-// REQUIRES: linux
+// REQUIRES: system-linux
 
 void clang_analyzer_eval(int);
 
diff --git a/clang/test/Analysis/ctu-on-demand-parsing.cpp b/clang/test/Analysis/ctu-on-demand-parsing.cpp
index 058269662fb3a..e4e998c8f64c3 100644
--- a/clang/test/Analysis/ctu-on-demand-parsing.cpp
+++ b/clang/test/Analysis/ctu-on-demand-parsing.cpp
@@ -30,7 +30,7 @@
 // CHECK: CTU loaded AST file: {{.*}}ctu-chain.cpp
 //
 // FIXME: Path handling should work on all platforms.
-// REQUIRES: linux
+// REQUIRES: system-linux
 
 #include "ctu-hdr.h"
 

From 595270ae39671eed49b75983beeab13de74a342b Mon Sep 17 00:00:00 2001
From: Sjoerd Meijer 
Date: Mon, 13 Jul 2020 11:53:09 +0100
Subject: [PATCH 091/771] [ARM][MVE] Refactor option
 -disable-mve-tail-predication

This refactors option -disable-mve-tail-predication to take different arguments
so that we have 1 option to control tail-predication rather than several
different ones.

This is also a prep step for D82953, in which we want to reject reductions
unless that is requested with this option.

Differential Revision: https://reviews.llvm.org/D83133
---
 .../lib/Target/ARM/ARMTargetTransformInfo.cpp |  6 ++--
 llvm/lib/Target/ARM/ARMTargetTransformInfo.h  | 10 ++++++
 llvm/lib/Target/ARM/MVETailPredication.cpp    | 35 +++++++++++++------
 .../LowOverheadLoops/basic-tail-pred.ll       |  2 +-
 .../LowOverheadLoops/clear-maskedinsts.ll     |  2 +-
 .../cond-vector-reduce-mve-codegen.ll         |  2 +-
 .../LowOverheadLoops/extending-loads.ll       |  2 +-
 .../Thumb2/LowOverheadLoops/fast-fp-loops.ll  |  2 +-
 .../LowOverheadLoops/lsr-profitable-chain.ll  |  2 +-
 .../LowOverheadLoops/mve-tail-data-types.ll   |  2 +-
 .../CodeGen/Thumb2/LowOverheadLoops/nested.ll |  2 +-
 .../Thumb2/LowOverheadLoops/reductions.ll     |  2 +-
 .../LowOverheadLoops/tail-pred-const.ll       |  2 +-
 .../tail-pred-intrinsic-add-sat.ll            |  3 +-
 .../tail-pred-intrinsic-fabs.ll               |  3 +-
 .../tail-pred-intrinsic-round.ll              |  3 +-
 .../tail-pred-intrinsic-sub-sat.ll            |  3 +-
 .../LowOverheadLoops/tail-pred-narrow.ll      |  2 +-
 .../tail-pred-pattern-fail.ll                 |  2 +-
 .../LowOverheadLoops/tail-pred-widen.ll       |  2 +-
 .../Thumb2/LowOverheadLoops/tail-reduce.ll    |  6 ++--
 .../varying-outer-2d-reduction.ll             |  2 +-
 .../LowOverheadLoops/vector-arith-codegen.ll  |  2 +-
 .../vector-reduce-mve-tail.ll                 |  2 +-
 .../Thumb2/LowOverheadLoops/vector-unroll.ll  |  2 +-
 llvm/test/CodeGen/Thumb2/mve-fma-loops.ll     |  2 +-
 .../ARM/prefer-tail-loop-folding.ll           | 16 ++++-----
 .../ARM/tail-folding-counting-down.ll         |  4 +--
 .../LoopVectorize/ARM/tail-loop-folding.ll    |  4 +--
 29 files changed, 79 insertions(+), 50 deletions(-)

diff --git a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
index 74b1331216a05..575e6171059da 100644
--- a/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMTargetTransformInfo.cpp
@@ -45,7 +45,7 @@ static cl::opt DisableLowOverheadLoops(
   "disable-arm-loloops", cl::Hidden, cl::init(false),
   cl::desc("Disable the generation of low-overhead loops"));
 
-extern cl::opt DisableTailPredication;
+extern cl::opt EnableTailPredication;
 
 extern cl::opt EnableMaskedGatherScatters;
 
@@ -1458,7 +1458,7 @@ bool ARMTTIImpl::preferPredicateOverEpilogue(Loop *L, LoopInfo *LI,
                                              TargetLibraryInfo *TLI,
                                              DominatorTree *DT,
                                              const LoopAccessInfo *LAI) {
-  if (DisableTailPredication)
+  if (!EnableTailPredication)
     return false;
 
   // Creating a predicated vector loop is the first step for generating a
@@ -1501,7 +1501,7 @@ bool ARMTTIImpl::preferPredicateOverEpilogue(Loop *L, LoopInfo *LI,
 }
 
 bool ARMTTIImpl::emitGetActiveLaneMask() const {
-  if (!ST->hasMVEIntegerOps() || DisableTailPredication)
+  if (!ST->hasMVEIntegerOps() || !EnableTailPredication)
     return false;
 
   // Intrinsic @llvm.get.active.lane.mask is supported.
diff --git a/llvm/lib/Target/ARM/ARMTargetTransformInfo.h b/llvm/lib/Target/ARM/ARMTargetTransformInfo.h
index 537a546361eeb..7bf6de4bffe07 100644
--- a/llvm/lib/Target/ARM/ARMTargetTransformInfo.h
+++ b/llvm/lib/Target/ARM/ARMTargetTransformInfo.h
@@ -38,6 +38,16 @@ class ScalarEvolution;
 class Type;
 class Value;
 
+namespace TailPredication {
+  enum Mode {
+    Disabled = 0,
+    EnabledNoReductions,
+    Enabled,
+    ForceEnabledNoReductions,
+    ForceEnabled
+  };
+}
+
 class ARMTTIImpl : public BasicTTIImplBase {
   using BaseT = BasicTTIImplBase;
   using TTI = TargetTransformInfo;
diff --git a/llvm/lib/Target/ARM/MVETailPredication.cpp b/llvm/lib/Target/ARM/MVETailPredication.cpp
index 6583dcb77e1ed..5bf3522ab2e64 100644
--- a/llvm/lib/Target/ARM/MVETailPredication.cpp
+++ b/llvm/lib/Target/ARM/MVETailPredication.cpp
@@ -42,6 +42,7 @@
 
 #include "ARM.h"
 #include "ARMSubtarget.h"
+#include "ARMTargetTransformInfo.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/LoopPass.h"
 #include "llvm/Analysis/ScalarEvolution.h"
@@ -64,16 +65,27 @@ using namespace llvm;
 #define DEBUG_TYPE "mve-tail-predication"
 #define DESC "Transform predicated vector loops to use MVE tail predication"
 
-static cl::opt
-ForceTailPredication("force-mve-tail-predication", cl::Hidden, cl::init(false),
-                     cl::desc("Force MVE tail-predication even if it might be "
-                              "unsafe (e.g. possible overflow in loop "
-                              "counters)"));
+cl::opt EnableTailPredication(
+   "tail-predication", cl::desc("MVE tail-predication options"),
+   cl::init(TailPredication::Disabled),
+   cl::values(clEnumValN(TailPredication::Disabled, "disabled",
+                         "Don't tail-predicate loops"),
+              clEnumValN(TailPredication::EnabledNoReductions,
+                         "enabled-no-reductions",
+                         "Enable tail-predication, but not for reduction loops"),
+              clEnumValN(TailPredication::Enabled,
+                         "enabled",
+                         "Enable tail-predication, including reduction loops"),
+              clEnumValN(TailPredication::ForceEnabledNoReductions,
+                         "force-enabled-no-reductions",
+                         "Enable tail-predication, but not for reduction loops, "
+                         "and force this which might be unsafe"),
+              clEnumValN(TailPredication::ForceEnabled,
+                         "force-enabled",
+                         "Enable tail-predication, including reduction loops, "
+                         "and force this which might be unsafe")));
+
 
-cl::opt
-DisableTailPredication("disable-mve-tail-predication", cl::Hidden,
-                       cl::init(true),
-                       cl::desc("Disable MVE Tail Predication"));
 namespace {
 
 class MVETailPredication : public LoopPass {
@@ -146,7 +158,7 @@ static bool IsMasked(Instruction *I) {
 }
 
 bool MVETailPredication::runOnLoop(Loop *L, LPPassManager&) {
-  if (skipLoop(L) || DisableTailPredication)
+  if (skipLoop(L) || !EnableTailPredication)
     return false;
 
   MaskedInsts.clear();
@@ -346,6 +358,9 @@ static void Cleanup(SetVector &MaybeDead, Loop *L) {
 //    vector width.
 bool MVETailPredication::IsSafeActiveMask(IntrinsicInst *ActiveLaneMask,
     Value *TripCount, FixedVectorType *VecTy) {
+  bool ForceTailPredication =
+    EnableTailPredication == TailPredication::ForceEnabledNoReductions ||
+    EnableTailPredication == TailPredication::ForceEnabled;
   // 1) Test whether entry to the loop is protected by a conditional
   // BTC + 1 < 0. In other words, if the scalar trip count overflows,
   // becomes negative, we shouldn't enter the loop and creating
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/basic-tail-pred.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/basic-tail-pred.ll
index a00af0d6a9ec4..5fced6ad29e2a 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/basic-tail-pred.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/basic-tail-pred.ll
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false -mattr=+mve,+lob %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=enabled -mattr=+mve,+lob %s -S -o - | FileCheck %s
 
 ; CHECK-LABEL: mul_v16i8
 ; CHECK-NOT: %num.elements = add i32 %trip.count.minus.1, 1
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/clear-maskedinsts.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/clear-maskedinsts.ll
index dab642b94be05..56343a6d65cb5 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/clear-maskedinsts.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/clear-maskedinsts.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=thumbv8.1m.main -mattr=+mve.fp -mve-tail-predication -disable-mve-tail-predication=false %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mattr=+mve.fp -mve-tail-predication -tail-predication=enabled %s -S -o - | FileCheck %s
 
 define hidden i32 @_Z4loopPiPjiS0_i(i32* noalias nocapture readonly %s1, i32* noalias nocapture readonly %s2, i32 %x, i32* noalias nocapture %d, i32 %n) {
 ; CHECK-LABEL: @_Z4loopPiPjiS0_i(
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/cond-vector-reduce-mve-codegen.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/cond-vector-reduce-mve-codegen.ll
index bf6e92a1c8838..e98276e258abd 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/cond-vector-reduce-mve-codegen.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/cond-vector-reduce-mve-codegen.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -disable-mve-tail-predication=false --verify-machineinstrs %s -o - | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -tail-predication=enabled --verify-machineinstrs %s -o - | FileCheck %s
 
 define dso_local i32 @vpsel_mul_reduce_add(i32* noalias nocapture readonly %a, i32* noalias nocapture readonly %b, i32* noalias nocapture readonly %c, i32 %N) {
 ; CHECK-LABEL: vpsel_mul_reduce_add:
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/extending-loads.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/extending-loads.ll
index 8d201a23a6898..1fda5c08a0375 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/extending-loads.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/extending-loads.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -disable-mve-tail-predication=false %s -o - | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -tail-predication=enabled %s -o - | FileCheck %s
 
 define dso_local arm_aapcs_vfpcc void @sext_i8(i16* noalias nocapture %a, i8* nocapture readonly %b, i32 %N) {
 ; CHECK-LABEL: sext_i8:
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/fast-fp-loops.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/fast-fp-loops.ll
index 8c18159c24c56..d8d6af3b9a8dc 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/fast-fp-loops.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/fast-fp-loops.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve.fp,+fp-armv8d16sp,+fp16,+fullfp16 -disable-mve-tail-predication=false %s -o - | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve.fp,+fp-armv8d16sp,+fp16,+fullfp16 -tail-predication=enabled %s -o - | FileCheck %s
 
 define arm_aapcs_vfpcc void @fast_float_mul(float* nocapture %a, float* nocapture readonly %b, float* nocapture readonly %c, i32 %N) {
 ; CHECK-LABEL: fast_float_mul:
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/lsr-profitable-chain.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/lsr-profitable-chain.ll
index bc2c7e084ea7c..fddbfa8b66207 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/lsr-profitable-chain.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/lsr-profitable-chain.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -O3 -disable-mve-tail-predication=false -mtriple=thumbv8.1m.main -mattr=+mve,+mve.fp %s -o - | FileCheck %s
+; RUN: llc -O3 -tail-predication=enabled -mtriple=thumbv8.1m.main -mattr=+mve,+mve.fp %s -o - | FileCheck %s
 
 target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
 target triple = "thumbv8.1m-arm-none-eabi"
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mve-tail-data-types.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mve-tail-data-types.ll
index 6c1273db3f80f..428c703dd341e 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mve-tail-data-types.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/mve-tail-data-types.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -disable-mve-tail-predication=false %s -o - | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -tail-predication=enabled %s -o - | FileCheck %s
 
 define arm_aapcs_vfpcc i32 @test_acc_scalar_char(i8 zeroext %a, i8* nocapture readonly %b, i32 %N) {
 ; CHECK-LABEL: test_acc_scalar_char:
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/nested.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/nested.ll
index 64702cc3c3155..548ba396bed42 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/nested.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/nested.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=armv8.1m.main -mattr=+mve -S -mve-tail-predication -disable-mve-tail-predication=false %s -o - | FileCheck %s
+; RUN: opt -mtriple=armv8.1m.main -mattr=+mve -S -mve-tail-predication -tail-predication=enabled %s -o - | FileCheck %s
 
 define void @mat_vec_sext_i16(i16** nocapture readonly %A, i16* nocapture readonly %B, i32* noalias nocapture %C, i32 %N) {
 ; CHECK-LABEL: @mat_vec_sext_i16(
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
index 12c3ca0525f21..66601dd66cb29 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/reductions.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -disable-mve-tail-predication=false %s -o - | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -tail-predication=enabled %s -o - | FileCheck %s
 
 define dso_local arm_aapcs_vfpcc zeroext i8 @one_loop_add_add_v16i8(i8* nocapture readonly %a, i8* nocapture readonly %b, i32 %N) local_unnamed_addr {
 ; CHECK-LABEL: one_loop_add_add_v16i8:
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-const.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-const.ll
index 13d750310a56c..065e534dd55bd 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-const.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-const.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false -mattr=+mve %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=enabled -mattr=+mve %s -S -o - | FileCheck %s
 
 define dso_local void @foo(i32* noalias nocapture %A, i32* noalias nocapture readonly %B, i32* noalias nocapture readonly %C, i32* noalias nocapture readnone %D, i32 %N) local_unnamed_addr #0 {
 ; CHECK-LABEL: @foo(
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-add-sat.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-add-sat.ll
index d405657f4d17e..e9facfda61335 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-add-sat.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-add-sat.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve -verify-machineinstrs -disable-mve-tail-predication=false -o - %s | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve -verify-machineinstrs -tail-predication=enabled -o - %s | FileCheck %s
+
 define arm_aapcs_vfpcc void @uadd_sat(i16* noalias nocapture readonly %pSrcA, i16* noalias nocapture readonly %pSrcB, i16* noalias nocapture %pDst, i32 %blockSize) {
 ; CHECK-LABEL: uadd_sat:
 ; CHECK:       @ %bb.0: @ %entry
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-fabs.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-fabs.ll
index d3247a3fd28e7..87f23adf7ffa5 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-fabs.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-fabs.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp -verify-machineinstrs -disable-mve-tail-predication=false -o - %s | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp -verify-machineinstrs -tail-predication=enabled -o - %s | FileCheck %s
+
 define arm_aapcs_vfpcc void @fabs(float* noalias nocapture readonly %pSrcA, float* noalias nocapture %pDst, i32 %blockSize) {
 ; CHECK-LABEL: fabs:
 ; CHECK:       @ %bb.0: @ %entry
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-round.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-round.ll
index 962e9df3dc1e9..e72e81da7e7c1 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-round.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-round.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp -verify-machineinstrs -disable-mve-tail-predication=false -o - %s | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp -verify-machineinstrs -tail-predication=enabled -o - %s | FileCheck %s
+
 define arm_aapcs_vfpcc void @round(float* noalias nocapture readonly %pSrcA, float* noalias nocapture %pDst, i32 %n) #0 {
 ; CHECK-LABEL: round:
 ; CHECK:       @ %bb.0: @ %entry
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-sub-sat.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-sub-sat.ll
index 790311a54aa1d..3c7ae4dc734ad 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-sub-sat.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-intrinsic-sub-sat.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve -verify-machineinstrs -disable-mve-tail-predication=false -o - %s | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve -verify-machineinstrs -tail-predication=enabled -o - %s | FileCheck %s
+
 define arm_aapcs_vfpcc void @usub_sat(i16* noalias nocapture readonly %pSrcA, i16* noalias nocapture readonly %pSrcB, i16* noalias nocapture %pDst, i32 %blockSize) {
 ; CHECK-LABEL: usub_sat:
 ; CHECK:       @ %bb.0: @ %entry
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-narrow.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-narrow.ll
index 8c1534be77db0..52cd8fdc6d798 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-narrow.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-narrow.ll
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false -mattr=+mve,+lob %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=enabled -mattr=+mve,+lob %s -S -o - | FileCheck %s
 
 ; TODO: We should be able to generate a vctp for the loads.
 ; CHECK-LABEL: trunc_v4i32_v4i16
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-pattern-fail.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-pattern-fail.ll
index 1926bbeeaa70f..8e46e3385385e 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-pattern-fail.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-pattern-fail.ll
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false -mattr=+mve,+lob %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=enabled -mattr=+mve,+lob %s -S -o - | FileCheck %s
 
 ; The following functions should all fail to become tail-predicated.
 ; CHECK-NOT: call i32 @llvm.arm.vctp
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-widen.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-widen.ll
index 3a9d3d1171266..b40b36ced4af2 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-widen.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-pred-widen.ll
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false -mattr=+mve,+lob %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=enabled -mattr=+mve,+lob %s -S -o - | FileCheck %s
 
 ; CHECK-LABEL: expand_v8i16_v8i32
 ; CHECK-NOT: call i32 @llvm.arm.mve.vctp
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-reduce.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-reduce.ll
index 5c753134744d6..f3055bc8a575f 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-reduce.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/tail-reduce.ll
@@ -1,6 +1,6 @@
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false -mattr=+mve %s -S -o - | FileCheck %s
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false \
-; RUN:    -force-mve-tail-predication -mattr=+mve %s -S -o - | FileCheck %s --check-prefix=FORCE
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=enabled -mattr=+mve %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=force-enabled \
+; RUN:    -mattr=+mve %s -S -o - | FileCheck %s --check-prefix=FORCE
 
 ; CHECK-LABEL: reduction_i32
 ; CHECK: phi i32 [ 0, %vector.ph ]
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/varying-outer-2d-reduction.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/varying-outer-2d-reduction.ll
index f1242db364851..4db17c074643f 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/varying-outer-2d-reduction.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/varying-outer-2d-reduction.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -disable-mve-tail-predication=false %s -o - | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -tail-predication=enabled %s -o - | FileCheck %s
 
 define dso_local void @varying_outer_2d_reduction(i16* nocapture readonly %Input, i16* nocapture %Output, i16 signext %Size, i16 signext %N, i16 signext %Scale) local_unnamed_addr {
 ; CHECK-LABEL: varying_outer_2d_reduction:
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-arith-codegen.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-arith-codegen.ll
index 26a570ac4c29b..615334300c283 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-arith-codegen.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-arith-codegen.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=armv8.1m.main -mattr=+mve -disable-mve-tail-predication=false --verify-machineinstrs %s -o - | FileCheck %s
+; RUN: llc -mtriple=armv8.1m.main -mattr=+mve -tail-predication=enabled --verify-machineinstrs %s -o - | FileCheck %s
 
 define dso_local i32 @mul_reduce_add(i32* noalias nocapture readonly %a, i32* noalias nocapture readonly %b, i32 %N) {
 ; CHECK-LABEL: mul_reduce_add:
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-reduce-mve-tail.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-reduce-mve-tail.ll
index aaeae75e072f7..e10cc3153b9c9 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-reduce-mve-tail.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-reduce-mve-tail.ll
@@ -1,5 +1,5 @@
 
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false -mattr=+mve %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=enabled -mattr=+mve %s -S -o - | FileCheck %s
 
 ; CHECK-LABEL: vec_mul_reduce_add
 
diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-unroll.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-unroll.ll
index 19d9c89dabca8..f1a35af8b57ed 100644
--- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-unroll.ll
+++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/vector-unroll.ll
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -disable-mve-tail-predication=false -mattr=+mve,+lob %s -S -o - | FileCheck %s
+; RUN: opt -mtriple=thumbv8.1m.main -mve-tail-predication -tail-predication=enabled -mattr=+mve,+lob %s -S -o - | FileCheck %s
 
 ; TODO: The unrolled pattern is preventing the transform
 ; CHECK-LABEL: mul_v16i8_unroll
diff --git a/llvm/test/CodeGen/Thumb2/mve-fma-loops.ll b/llvm/test/CodeGen/Thumb2/mve-fma-loops.ll
index 0ba224415b67e..306f31be27f96 100644
--- a/llvm/test/CodeGen/Thumb2/mve-fma-loops.ll
+++ b/llvm/test/CodeGen/Thumb2/mve-fma-loops.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp -verify-machineinstrs -disable-mve-tail-predication=false %s -o - | FileCheck %s
+; RUN: llc -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp -verify-machineinstrs -tail-predication=enabled %s -o - | FileCheck %s
 
 define arm_aapcs_vfpcc void @fmas1(float* nocapture readonly %x, float* nocapture readonly %y, float* noalias nocapture %z, float %a, i32 %n) {
 ; CHECK-LABEL: fmas1:
diff --git a/llvm/test/Transforms/LoopVectorize/ARM/prefer-tail-loop-folding.ll b/llvm/test/Transforms/LoopVectorize/ARM/prefer-tail-loop-folding.ll
index ff3e03c7bad42..ac6bb56ff5f80 100644
--- a/llvm/test/Transforms/LoopVectorize/ARM/prefer-tail-loop-folding.ll
+++ b/llvm/test/Transforms/LoopVectorize/ARM/prefer-tail-loop-folding.ll
@@ -1,19 +1,19 @@
 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf \
-; RUN:   -disable-mve-tail-predication=false -loop-vectorize -S < %s | \
+; RUN:   -tail-predication=enabled -loop-vectorize -S < %s | \
 ; RUN:   FileCheck %s -check-prefixes=CHECK,PREFER-FOLDING
 
 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=-mve \
-; RUN:   -disable-mve-tail-predication=false -loop-vectorize \
+; RUN:   -tail-predication=enabled -loop-vectorize \
 ; RUN:   -enable-arm-maskedldst=true -S < %s | \
 ; RUN:   FileCheck %s -check-prefixes=CHECK,NO-FOLDING
 
 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=+mve \
-; RUN:   -disable-mve-tail-predication=false -loop-vectorize \
+; RUN:   -tail-predication=enabled -loop-vectorize \
 ; RUN:   -enable-arm-maskedldst=false -S < %s | \
 ; RUN:   FileCheck %s -check-prefixes=CHECK,NO-FOLDING
 
 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=+mve \
-; RUN:   -disable-mve-tail-predication=true -loop-vectorize \
+; RUN:   -tail-predication=disabled -loop-vectorize \
 ; RUN:   -enable-arm-maskedldst=true -S < %s | \
 ; RUN:   FileCheck %s -check-prefixes=CHECK,NO-FOLDING
 
@@ -21,24 +21,24 @@
 ; 'isHardwareLoopProfitable' return false, so that we test avoiding folding for
 ; these cases.
 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=+mve,-lob \
-; RUN:   -disable-mve-tail-predication=false -loop-vectorize \
+; RUN:   -tail-predication=enabled -loop-vectorize \
 ; RUN:   -enable-arm-maskedldst=true -S < %s | \
 ; RUN:   FileCheck %s -check-prefixes=CHECK,NO-FOLDING
 
 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=+mve.fp \
-; RUN:   -disable-mve-tail-predication=false -loop-vectorize \
+; RUN:   -tail-predication=enabled -loop-vectorize \
 ; RUN:   -enable-arm-maskedldst=true -S < %s | \
 ; RUN:   FileCheck %s -check-prefixes=CHECK,PREFER-FOLDING
 
 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=+mve.fp \
 ; RUN:   -prefer-predicate-over-epilog=false \
-; RUN:   -disable-mve-tail-predication=false -loop-vectorize \
+; RUN:   -tail-predication=enabled -loop-vectorize \
 ; RUN:   -enable-arm-maskedldst=true -S < %s | \
 ; RUN:   FileCheck %s -check-prefixes=CHECK,NO-FOLDING
 
 ; RUN: opt -mtriple=thumbv8.1m.main-arm-eabihf -mattr=+mve.fp \
 ; RUN:   -prefer-predicate-over-epilog=true \
-; RUN:   -disable-mve-tail-predication=false -loop-vectorize \
+; RUN:   -tail-predication=enabled -loop-vectorize \
 ; RUN:   -enable-arm-maskedldst=true -S < %s | \
 ; RUN:   FileCheck %s -check-prefixes=CHECK,FOLDING-OPT
 
diff --git a/llvm/test/Transforms/LoopVectorize/ARM/tail-folding-counting-down.ll b/llvm/test/Transforms/LoopVectorize/ARM/tail-folding-counting-down.ll
index 23ecf5b6015cb..8a327f163b121 100644
--- a/llvm/test/Transforms/LoopVectorize/ARM/tail-folding-counting-down.ll
+++ b/llvm/test/Transforms/LoopVectorize/ARM/tail-folding-counting-down.ll
@@ -1,6 +1,6 @@
 ; RUN: opt < %s -loop-vectorize -S | FileCheck %s --check-prefixes=COMMON,DEFAULT
-; RUN: opt < %s -loop-vectorize -disable-mve-tail-predication=false  -prefer-predicate-over-epilog -S | FileCheck %s --check-prefixes=COMMON,CHECK-TF,CHECK-PREFER
-; RUN: opt < %s -loop-vectorize -disable-mve-tail-predication=false -S | FileCheck %s --check-prefixes=COMMON,CHECK-TF,CHECK-ENABLE-TP
+; RUN: opt < %s -loop-vectorize -tail-predication=enabled -prefer-predicate-over-epilog -S | FileCheck %s --check-prefixes=COMMON,CHECK-TF,CHECK-PREFER
+; RUN: opt < %s -loop-vectorize -tail-predication=enabled -S | FileCheck %s --check-prefixes=COMMON,CHECK-TF,CHECK-ENABLE-TP
 
 target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
 target triple = "thumbv8.1m.main-arm-unknown-eabihf"
diff --git a/llvm/test/Transforms/LoopVectorize/ARM/tail-loop-folding.ll b/llvm/test/Transforms/LoopVectorize/ARM/tail-loop-folding.ll
index f3e1af6f14ffc..eda3c115c0f6b 100644
--- a/llvm/test/Transforms/LoopVectorize/ARM/tail-loop-folding.ll
+++ b/llvm/test/Transforms/LoopVectorize/ARM/tail-loop-folding.ll
@@ -1,7 +1,7 @@
-; RUN: opt < %s -loop-vectorize -disable-mve-tail-predication=false -S | \
+; RUN: opt < %s -loop-vectorize -tail-predication=enabled -S | \
 ; RUN:  FileCheck %s -check-prefixes=COMMON,CHECK
 
-; RUN: opt < %s -loop-vectorize -disable-mve-tail-predication=false -prefer-predicate-over-epilog -S | \
+; RUN: opt < %s -loop-vectorize -tail-predication=enabled -prefer-predicate-over-epilog -S | \
 ; RUN:   FileCheck -check-prefixes=COMMON,PREDFLAG %s
 
 target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"

From 591a3af5c7acc05617c0eacf6ae4f76bd8a9a6ce Mon Sep 17 00:00:00 2001
From: Sanjay Patel 
Date: Mon, 13 Jul 2020 08:51:09 -0400
Subject: [PATCH 092/771] [DAGCombiner] allow load/store merging if pairs can
 be rotated into place

This carves out an exception for a pair of consecutive loads that are
reversed from the consecutive order of a pair of stores. All of the
existing profitability/legality checks for the memops remain between
the 2 altered hunks of code.

This should give us the same x86 base-case asm that gcc gets in
PR41098 and PR44895:i
http://bugs.llvm.org/PR41098
http://bugs.llvm.org/PR44895

I think we are missing a potential subsequent conversion to use "movbe"
if the target supports that. That might be similar to what AArch64
would use to get "rev16".

Differential Revision:
---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 39 +++++++++---
 .../CodeGen/AArch64/merge-store-dependency.ll | 22 ++++---
 llvm/test/CodeGen/X86/stores-merging.ll       | 61 ++++++++-----------
 3 files changed, 70 insertions(+), 52 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 42e6e12f3f027..dd601bd5ca7e8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -16541,14 +16541,27 @@ bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl &StoreNodes,
   }
 
   while (NumConsecutiveStores >= 2 && LoadNodes.size() >= 2) {
-    // If we have load/store pair instructions and we only have two values,
-    // don't bother merging.
     Align RequiredAlignment;
-    if (LoadNodes.size() == 2 && TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
-        StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
-      StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
-      LoadNodes.erase(LoadNodes.begin(), LoadNodes.begin() + 2);
-      break;
+    bool NeedRotate = false;
+    if (LoadNodes.size() == 2) {
+      // If we have load/store pair instructions and we only have two values,
+      // don't bother merging.
+      if (TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
+          StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
+        StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
+        LoadNodes.erase(LoadNodes.begin(), LoadNodes.begin() + 2);
+        break;
+      }
+      // If the loads are reversed, see if we can rotate the halves into place.
+      int64_t Offset0 = LoadNodes[0].OffsetFromBase;
+      int64_t Offset1 = LoadNodes[1].OffsetFromBase;
+      EVT PairVT = EVT::getIntegerVT(Context, ElementSizeBytes * 8 * 2);
+      if (Offset0 - Offset1 == ElementSizeBytes &&
+          (hasOperation(ISD::ROTL, PairVT) ||
+           hasOperation(ISD::ROTR, PairVT))) {
+        std::swap(LoadNodes[0], LoadNodes[1]);
+        NeedRotate = true;
+      }
     }
     LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
     unsigned FirstStoreAS = FirstInChain->getAddressSpace();
@@ -16713,8 +16726,18 @@ bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl &StoreNodes,
       NewLoad = DAG.getLoad(
           JointMemOpVT, LoadDL, FirstLoad->getChain(), FirstLoad->getBasePtr(),
           FirstLoad->getPointerInfo(), FirstLoadAlign, LdMMOFlags);
+      SDValue StoreOp = NewLoad;
+      if (NeedRotate) {
+        unsigned LoadWidth = ElementSizeBytes * 8 * 2;
+        assert(JointMemOpVT == EVT::getIntegerVT(Context, LoadWidth) &&
+               "Unexpected type for rotate-able load pair");
+        SDValue RotAmt =
+            DAG.getShiftAmountConstant(LoadWidth / 2, JointMemOpVT, LoadDL);
+        // Target can convert to the identical ROTR if it does not have ROTL.
+        StoreOp = DAG.getNode(ISD::ROTL, LoadDL, JointMemOpVT, NewLoad, RotAmt);
+      }
       NewStore = DAG.getStore(
-          NewStoreChain, StoreDL, NewLoad, FirstInChain->getBasePtr(),
+          NewStoreChain, StoreDL, StoreOp, FirstInChain->getBasePtr(),
           FirstInChain->getPointerInfo(), FirstStoreAlign, StMMOFlags);
     } else { // This must be the truncstore/extload case
       EVT ExtendedTy =
diff --git a/llvm/test/CodeGen/AArch64/merge-store-dependency.ll b/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
index 77b7012d2ed1e..6850846fec068 100644
--- a/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
+++ b/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
@@ -95,6 +95,8 @@ exit:
   ret void
 }
 
+; TODO: rev16?
+
 define void @rotate16_in_place(i8* %p) {
 ; A53-LABEL: rotate16_in_place:
 ; A53:       // %bb.0:
@@ -112,6 +114,8 @@ define void @rotate16_in_place(i8* %p) {
   ret void
 }
 
+; TODO: rev16?
+
 define void @rotate16(i8* %p, i8* %q) {
 ; A53-LABEL: rotate16:
 ; A53:       // %bb.0:
@@ -134,10 +138,9 @@ define void @rotate16(i8* %p, i8* %q) {
 define void @rotate32_in_place(i16* %p) {
 ; A53-LABEL: rotate32_in_place:
 ; A53:       // %bb.0:
-; A53-NEXT:    ldrh w8, [x0, #2]
-; A53-NEXT:    ldrh w9, [x0]
-; A53-NEXT:    strh w8, [x0]
-; A53-NEXT:    strh w9, [x0, #2]
+; A53-NEXT:    ldr w8, [x0]
+; A53-NEXT:    ror w8, w8, #16
+; A53-NEXT:    str w8, [x0]
 ; A53-NEXT:    ret
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -151,10 +154,9 @@ define void @rotate32_in_place(i16* %p) {
 define void @rotate32(i16* %p) {
 ; A53-LABEL: rotate32:
 ; A53:       // %bb.0:
-; A53-NEXT:    ldrh w8, [x0, #2]
-; A53-NEXT:    ldrh w9, [x0]
-; A53-NEXT:    strh w8, [x0, #84]
-; A53-NEXT:    strh w9, [x0, #86]
+; A53-NEXT:    ldr w8, [x0]
+; A53-NEXT:    ror w8, w8, #16
+; A53-NEXT:    str w8, [x0, #84]
 ; A53-NEXT:    ret
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -167,6 +169,8 @@ define void @rotate32(i16* %p) {
   ret void
 }
 
+; Prefer paired memops over rotate.
+
 define void @rotate64_in_place(i32* %p) {
 ; A53-LABEL: rotate64_in_place:
 ; A53:       // %bb.0:
@@ -182,6 +186,8 @@ define void @rotate64_in_place(i32* %p) {
   ret void
 }
 
+; Prefer paired memops over rotate.
+
 define void @rotate64(i32* %p) {
 ; A53-LABEL: rotate64:
 ; A53:       // %bb.0:
diff --git a/llvm/test/CodeGen/X86/stores-merging.ll b/llvm/test/CodeGen/X86/stores-merging.ll
index 768684067f32f..60fd01eac0960 100644
--- a/llvm/test/CodeGen/X86/stores-merging.ll
+++ b/llvm/test/CodeGen/X86/stores-merging.ll
@@ -246,10 +246,7 @@ define void @pr43446_1(i8* %a) {
 define void @rotate16_in_place(i8* %p) {
 ; CHECK-LABEL: rotate16_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movb (%rdi), %al
-; CHECK-NEXT:    movb 1(%rdi), %cl
-; CHECK-NEXT:    movb %cl, (%rdi)
-; CHECK-NEXT:    movb %al, 1(%rdi)
+; CHECK-NEXT:    rolw $8, (%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i8, i8* %p, i64 0
   %p1 = getelementptr i8, i8* %p, i64 1
@@ -263,10 +260,9 @@ define void @rotate16_in_place(i8* %p) {
 define void @rotate16(i8* %p, i8* %q) {
 ; CHECK-LABEL: rotate16:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movb (%rdi), %al
-; CHECK-NEXT:    movb 1(%rdi), %cl
-; CHECK-NEXT:    movb %cl, (%rsi)
-; CHECK-NEXT:    movb %al, 1(%rsi)
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    rolw $8, %ax
+; CHECK-NEXT:    movw %ax, (%rsi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i8, i8* %p, i64 0
   %p1 = getelementptr i8, i8* %p, i64 1
@@ -282,10 +278,7 @@ define void @rotate16(i8* %p, i8* %q) {
 define void @rotate32_in_place(i16* %p) {
 ; CHECK-LABEL: rotate32_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movzwl (%rdi), %eax
-; CHECK-NEXT:    movzwl 2(%rdi), %ecx
-; CHECK-NEXT:    movw %cx, (%rdi)
-; CHECK-NEXT:    movw %ax, 2(%rdi)
+; CHECK-NEXT:    roll $16, (%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -299,10 +292,9 @@ define void @rotate32_in_place(i16* %p) {
 define void @rotate32(i16* %p) {
 ; CHECK-LABEL: rotate32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movzwl (%rdi), %eax
-; CHECK-NEXT:    movzwl 2(%rdi), %ecx
-; CHECK-NEXT:    movw %cx, 84(%rdi)
-; CHECK-NEXT:    movw %ax, 86(%rdi)
+; CHECK-NEXT:    movl (%rdi), %eax
+; CHECK-NEXT:    roll $16, %eax
+; CHECK-NEXT:    movl %eax, 84(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -318,10 +310,7 @@ define void @rotate32(i16* %p) {
 define void @rotate64_in_place(i32* %p) {
 ; CHECK-LABEL: rotate64_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl (%rdi), %eax
-; CHECK-NEXT:    movl 4(%rdi), %ecx
-; CHECK-NEXT:    movl %ecx, (%rdi)
-; CHECK-NEXT:    movl %eax, 4(%rdi)
+; CHECK-NEXT:    rolq $32, (%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i32, i32* %p, i64 0
   %p1 = getelementptr i32, i32* %p, i64 1
@@ -335,10 +324,9 @@ define void @rotate64_in_place(i32* %p) {
 define void @rotate64(i32* %p) {
 ; CHECK-LABEL: rotate64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl (%rdi), %eax
-; CHECK-NEXT:    movl 4(%rdi), %ecx
-; CHECK-NEXT:    movl %ecx, 8(%rdi)
-; CHECK-NEXT:    movl %eax, 12(%rdi)
+; CHECK-NEXT:    movq (%rdi), %rax
+; CHECK-NEXT:    rolq $32, %rax
+; CHECK-NEXT:    movq %rax, 8(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i32, i32* %p, i64 0
   %p1 = getelementptr i32, i32* %p, i64 1
@@ -354,10 +342,9 @@ define void @rotate64(i32* %p) {
 define void @rotate64_iterate(i16* %p) {
 ; CHECK-LABEL: rotate64_iterate:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl (%rdi), %eax
-; CHECK-NEXT:    movl 4(%rdi), %ecx
-; CHECK-NEXT:    movl %ecx, 84(%rdi)
-; CHECK-NEXT:    movl %eax, 88(%rdi)
+; CHECK-NEXT:    movq (%rdi), %rax
+; CHECK-NEXT:    rolq $32, %rax
+; CHECK-NEXT:    movq %rax, 84(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -378,6 +365,8 @@ define void @rotate64_iterate(i16* %p) {
   ret void
 }
 
+; TODO: recognize this as 2 rotates?
+
 define void @rotate32_consecutive(i16* %p) {
 ; CHECK-LABEL: rotate32_consecutive:
 ; CHECK:       # %bb.0:
@@ -409,17 +398,17 @@ define void @rotate32_consecutive(i16* %p) {
   ret void
 }
 
+; Same as above, but now the stores are not all consecutive.
+
 define void @rotate32_twice(i16* %p) {
 ; CHECK-LABEL: rotate32_twice:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movzwl (%rdi), %eax
-; CHECK-NEXT:    movzwl 2(%rdi), %ecx
-; CHECK-NEXT:    movzwl 4(%rdi), %edx
-; CHECK-NEXT:    movzwl 6(%rdi), %esi
-; CHECK-NEXT:    movw %cx, 84(%rdi)
-; CHECK-NEXT:    movw %ax, 86(%rdi)
-; CHECK-NEXT:    movw %si, 108(%rdi)
-; CHECK-NEXT:    movw %dx, 110(%rdi)
+; CHECK-NEXT:    movl (%rdi), %eax
+; CHECK-NEXT:    movl 4(%rdi), %ecx
+; CHECK-NEXT:    roll $16, %eax
+; CHECK-NEXT:    roll $16, %ecx
+; CHECK-NEXT:    movl %eax, 84(%rdi)
+; CHECK-NEXT:    movl %ecx, 108(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1

From f1bbf3acb42a7447c170b8248e310d8a61443377 Mon Sep 17 00:00:00 2001
From: Sanjay Patel 
Date: Mon, 13 Jul 2020 08:55:29 -0400
Subject: [PATCH 093/771] Revert "[DAGCombiner] allow load/store merging if
 pairs can be rotated into place"

This reverts commit 591a3af5c7acc05617c0eacf6ae4f76bd8a9a6ce.
The commit message was cut off and failed to include the review citation.
---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 39 +++---------
 .../CodeGen/AArch64/merge-store-dependency.ll | 22 +++----
 llvm/test/CodeGen/X86/stores-merging.ll       | 61 +++++++++++--------
 3 files changed, 52 insertions(+), 70 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index dd601bd5ca7e8..42e6e12f3f027 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -16541,27 +16541,14 @@ bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl &StoreNodes,
   }
 
   while (NumConsecutiveStores >= 2 && LoadNodes.size() >= 2) {
+    // If we have load/store pair instructions and we only have two values,
+    // don't bother merging.
     Align RequiredAlignment;
-    bool NeedRotate = false;
-    if (LoadNodes.size() == 2) {
-      // If we have load/store pair instructions and we only have two values,
-      // don't bother merging.
-      if (TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
-          StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
-        StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
-        LoadNodes.erase(LoadNodes.begin(), LoadNodes.begin() + 2);
-        break;
-      }
-      // If the loads are reversed, see if we can rotate the halves into place.
-      int64_t Offset0 = LoadNodes[0].OffsetFromBase;
-      int64_t Offset1 = LoadNodes[1].OffsetFromBase;
-      EVT PairVT = EVT::getIntegerVT(Context, ElementSizeBytes * 8 * 2);
-      if (Offset0 - Offset1 == ElementSizeBytes &&
-          (hasOperation(ISD::ROTL, PairVT) ||
-           hasOperation(ISD::ROTR, PairVT))) {
-        std::swap(LoadNodes[0], LoadNodes[1]);
-        NeedRotate = true;
-      }
+    if (LoadNodes.size() == 2 && TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
+        StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
+      StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
+      LoadNodes.erase(LoadNodes.begin(), LoadNodes.begin() + 2);
+      break;
     }
     LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
     unsigned FirstStoreAS = FirstInChain->getAddressSpace();
@@ -16726,18 +16713,8 @@ bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl &StoreNodes,
       NewLoad = DAG.getLoad(
           JointMemOpVT, LoadDL, FirstLoad->getChain(), FirstLoad->getBasePtr(),
           FirstLoad->getPointerInfo(), FirstLoadAlign, LdMMOFlags);
-      SDValue StoreOp = NewLoad;
-      if (NeedRotate) {
-        unsigned LoadWidth = ElementSizeBytes * 8 * 2;
-        assert(JointMemOpVT == EVT::getIntegerVT(Context, LoadWidth) &&
-               "Unexpected type for rotate-able load pair");
-        SDValue RotAmt =
-            DAG.getShiftAmountConstant(LoadWidth / 2, JointMemOpVT, LoadDL);
-        // Target can convert to the identical ROTR if it does not have ROTL.
-        StoreOp = DAG.getNode(ISD::ROTL, LoadDL, JointMemOpVT, NewLoad, RotAmt);
-      }
       NewStore = DAG.getStore(
-          NewStoreChain, StoreDL, StoreOp, FirstInChain->getBasePtr(),
+          NewStoreChain, StoreDL, NewLoad, FirstInChain->getBasePtr(),
           FirstInChain->getPointerInfo(), FirstStoreAlign, StMMOFlags);
     } else { // This must be the truncstore/extload case
       EVT ExtendedTy =
diff --git a/llvm/test/CodeGen/AArch64/merge-store-dependency.ll b/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
index 6850846fec068..77b7012d2ed1e 100644
--- a/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
+++ b/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
@@ -95,8 +95,6 @@ exit:
   ret void
 }
 
-; TODO: rev16?
-
 define void @rotate16_in_place(i8* %p) {
 ; A53-LABEL: rotate16_in_place:
 ; A53:       // %bb.0:
@@ -114,8 +112,6 @@ define void @rotate16_in_place(i8* %p) {
   ret void
 }
 
-; TODO: rev16?
-
 define void @rotate16(i8* %p, i8* %q) {
 ; A53-LABEL: rotate16:
 ; A53:       // %bb.0:
@@ -138,9 +134,10 @@ define void @rotate16(i8* %p, i8* %q) {
 define void @rotate32_in_place(i16* %p) {
 ; A53-LABEL: rotate32_in_place:
 ; A53:       // %bb.0:
-; A53-NEXT:    ldr w8, [x0]
-; A53-NEXT:    ror w8, w8, #16
-; A53-NEXT:    str w8, [x0]
+; A53-NEXT:    ldrh w8, [x0, #2]
+; A53-NEXT:    ldrh w9, [x0]
+; A53-NEXT:    strh w8, [x0]
+; A53-NEXT:    strh w9, [x0, #2]
 ; A53-NEXT:    ret
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -154,9 +151,10 @@ define void @rotate32_in_place(i16* %p) {
 define void @rotate32(i16* %p) {
 ; A53-LABEL: rotate32:
 ; A53:       // %bb.0:
-; A53-NEXT:    ldr w8, [x0]
-; A53-NEXT:    ror w8, w8, #16
-; A53-NEXT:    str w8, [x0, #84]
+; A53-NEXT:    ldrh w8, [x0, #2]
+; A53-NEXT:    ldrh w9, [x0]
+; A53-NEXT:    strh w8, [x0, #84]
+; A53-NEXT:    strh w9, [x0, #86]
 ; A53-NEXT:    ret
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -169,8 +167,6 @@ define void @rotate32(i16* %p) {
   ret void
 }
 
-; Prefer paired memops over rotate.
-
 define void @rotate64_in_place(i32* %p) {
 ; A53-LABEL: rotate64_in_place:
 ; A53:       // %bb.0:
@@ -186,8 +182,6 @@ define void @rotate64_in_place(i32* %p) {
   ret void
 }
 
-; Prefer paired memops over rotate.
-
 define void @rotate64(i32* %p) {
 ; A53-LABEL: rotate64:
 ; A53:       // %bb.0:
diff --git a/llvm/test/CodeGen/X86/stores-merging.ll b/llvm/test/CodeGen/X86/stores-merging.ll
index 60fd01eac0960..768684067f32f 100644
--- a/llvm/test/CodeGen/X86/stores-merging.ll
+++ b/llvm/test/CodeGen/X86/stores-merging.ll
@@ -246,7 +246,10 @@ define void @pr43446_1(i8* %a) {
 define void @rotate16_in_place(i8* %p) {
 ; CHECK-LABEL: rotate16_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    rolw $8, (%rdi)
+; CHECK-NEXT:    movb (%rdi), %al
+; CHECK-NEXT:    movb 1(%rdi), %cl
+; CHECK-NEXT:    movb %cl, (%rdi)
+; CHECK-NEXT:    movb %al, 1(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i8, i8* %p, i64 0
   %p1 = getelementptr i8, i8* %p, i64 1
@@ -260,9 +263,10 @@ define void @rotate16_in_place(i8* %p) {
 define void @rotate16(i8* %p, i8* %q) {
 ; CHECK-LABEL: rotate16:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movzwl (%rdi), %eax
-; CHECK-NEXT:    rolw $8, %ax
-; CHECK-NEXT:    movw %ax, (%rsi)
+; CHECK-NEXT:    movb (%rdi), %al
+; CHECK-NEXT:    movb 1(%rdi), %cl
+; CHECK-NEXT:    movb %cl, (%rsi)
+; CHECK-NEXT:    movb %al, 1(%rsi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i8, i8* %p, i64 0
   %p1 = getelementptr i8, i8* %p, i64 1
@@ -278,7 +282,10 @@ define void @rotate16(i8* %p, i8* %q) {
 define void @rotate32_in_place(i16* %p) {
 ; CHECK-LABEL: rotate32_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    roll $16, (%rdi)
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    movzwl 2(%rdi), %ecx
+; CHECK-NEXT:    movw %cx, (%rdi)
+; CHECK-NEXT:    movw %ax, 2(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -292,9 +299,10 @@ define void @rotate32_in_place(i16* %p) {
 define void @rotate32(i16* %p) {
 ; CHECK-LABEL: rotate32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl (%rdi), %eax
-; CHECK-NEXT:    roll $16, %eax
-; CHECK-NEXT:    movl %eax, 84(%rdi)
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    movzwl 2(%rdi), %ecx
+; CHECK-NEXT:    movw %cx, 84(%rdi)
+; CHECK-NEXT:    movw %ax, 86(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -310,7 +318,10 @@ define void @rotate32(i16* %p) {
 define void @rotate64_in_place(i32* %p) {
 ; CHECK-LABEL: rotate64_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    rolq $32, (%rdi)
+; CHECK-NEXT:    movl (%rdi), %eax
+; CHECK-NEXT:    movl 4(%rdi), %ecx
+; CHECK-NEXT:    movl %ecx, (%rdi)
+; CHECK-NEXT:    movl %eax, 4(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i32, i32* %p, i64 0
   %p1 = getelementptr i32, i32* %p, i64 1
@@ -324,9 +335,10 @@ define void @rotate64_in_place(i32* %p) {
 define void @rotate64(i32* %p) {
 ; CHECK-LABEL: rotate64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq (%rdi), %rax
-; CHECK-NEXT:    rolq $32, %rax
-; CHECK-NEXT:    movq %rax, 8(%rdi)
+; CHECK-NEXT:    movl (%rdi), %eax
+; CHECK-NEXT:    movl 4(%rdi), %ecx
+; CHECK-NEXT:    movl %ecx, 8(%rdi)
+; CHECK-NEXT:    movl %eax, 12(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i32, i32* %p, i64 0
   %p1 = getelementptr i32, i32* %p, i64 1
@@ -342,9 +354,10 @@ define void @rotate64(i32* %p) {
 define void @rotate64_iterate(i16* %p) {
 ; CHECK-LABEL: rotate64_iterate:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movq (%rdi), %rax
-; CHECK-NEXT:    rolq $32, %rax
-; CHECK-NEXT:    movq %rax, 84(%rdi)
+; CHECK-NEXT:    movl (%rdi), %eax
+; CHECK-NEXT:    movl 4(%rdi), %ecx
+; CHECK-NEXT:    movl %ecx, 84(%rdi)
+; CHECK-NEXT:    movl %eax, 88(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -365,8 +378,6 @@ define void @rotate64_iterate(i16* %p) {
   ret void
 }
 
-; TODO: recognize this as 2 rotates?
-
 define void @rotate32_consecutive(i16* %p) {
 ; CHECK-LABEL: rotate32_consecutive:
 ; CHECK:       # %bb.0:
@@ -398,17 +409,17 @@ define void @rotate32_consecutive(i16* %p) {
   ret void
 }
 
-; Same as above, but now the stores are not all consecutive.
-
 define void @rotate32_twice(i16* %p) {
 ; CHECK-LABEL: rotate32_twice:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl (%rdi), %eax
-; CHECK-NEXT:    movl 4(%rdi), %ecx
-; CHECK-NEXT:    roll $16, %eax
-; CHECK-NEXT:    roll $16, %ecx
-; CHECK-NEXT:    movl %eax, 84(%rdi)
-; CHECK-NEXT:    movl %ecx, 108(%rdi)
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    movzwl 2(%rdi), %ecx
+; CHECK-NEXT:    movzwl 4(%rdi), %edx
+; CHECK-NEXT:    movzwl 6(%rdi), %esi
+; CHECK-NEXT:    movw %cx, 84(%rdi)
+; CHECK-NEXT:    movw %ax, 86(%rdi)
+; CHECK-NEXT:    movw %si, 108(%rdi)
+; CHECK-NEXT:    movw %dx, 110(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1

From 2df46a574387663717a352eebad017979d3b5ef4 Mon Sep 17 00:00:00 2001
From: Sanjay Patel 
Date: Mon, 13 Jul 2020 08:57:00 -0400
Subject: [PATCH 094/771] [DAGCombiner] allow load/store merging if pairs can
 be rotated into place

This carves out an exception for a pair of consecutive loads that are
reversed from the consecutive order of a pair of stores. All of the
existing profitability/legality checks for the memops remain between
the 2 altered hunks of code.

This should give us the same x86 base-case asm that gcc gets in
PR41098 and PR44895:
http://bugs.llvm.org/PR41098
http://bugs.llvm.org/PR44895

I think we are missing a potential subsequent conversion to use "movbe"
if the target supports that. That might be similar to what AArch64
would use to get "rev16".

Differential Revision: https://reviews.llvm.org/D83567
---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 39 +++++++++---
 .../CodeGen/AArch64/merge-store-dependency.ll | 22 ++++---
 llvm/test/CodeGen/X86/stores-merging.ll       | 61 ++++++++-----------
 3 files changed, 70 insertions(+), 52 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 42e6e12f3f027..dd601bd5ca7e8 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -16541,14 +16541,27 @@ bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl &StoreNodes,
   }
 
   while (NumConsecutiveStores >= 2 && LoadNodes.size() >= 2) {
-    // If we have load/store pair instructions and we only have two values,
-    // don't bother merging.
     Align RequiredAlignment;
-    if (LoadNodes.size() == 2 && TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
-        StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
-      StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
-      LoadNodes.erase(LoadNodes.begin(), LoadNodes.begin() + 2);
-      break;
+    bool NeedRotate = false;
+    if (LoadNodes.size() == 2) {
+      // If we have load/store pair instructions and we only have two values,
+      // don't bother merging.
+      if (TLI.hasPairedLoad(MemVT, RequiredAlignment) &&
+          StoreNodes[0].MemNode->getAlign() >= RequiredAlignment) {
+        StoreNodes.erase(StoreNodes.begin(), StoreNodes.begin() + 2);
+        LoadNodes.erase(LoadNodes.begin(), LoadNodes.begin() + 2);
+        break;
+      }
+      // If the loads are reversed, see if we can rotate the halves into place.
+      int64_t Offset0 = LoadNodes[0].OffsetFromBase;
+      int64_t Offset1 = LoadNodes[1].OffsetFromBase;
+      EVT PairVT = EVT::getIntegerVT(Context, ElementSizeBytes * 8 * 2);
+      if (Offset0 - Offset1 == ElementSizeBytes &&
+          (hasOperation(ISD::ROTL, PairVT) ||
+           hasOperation(ISD::ROTR, PairVT))) {
+        std::swap(LoadNodes[0], LoadNodes[1]);
+        NeedRotate = true;
+      }
     }
     LSBaseSDNode *FirstInChain = StoreNodes[0].MemNode;
     unsigned FirstStoreAS = FirstInChain->getAddressSpace();
@@ -16713,8 +16726,18 @@ bool DAGCombiner::tryStoreMergeOfLoads(SmallVectorImpl &StoreNodes,
       NewLoad = DAG.getLoad(
           JointMemOpVT, LoadDL, FirstLoad->getChain(), FirstLoad->getBasePtr(),
           FirstLoad->getPointerInfo(), FirstLoadAlign, LdMMOFlags);
+      SDValue StoreOp = NewLoad;
+      if (NeedRotate) {
+        unsigned LoadWidth = ElementSizeBytes * 8 * 2;
+        assert(JointMemOpVT == EVT::getIntegerVT(Context, LoadWidth) &&
+               "Unexpected type for rotate-able load pair");
+        SDValue RotAmt =
+            DAG.getShiftAmountConstant(LoadWidth / 2, JointMemOpVT, LoadDL);
+        // Target can convert to the identical ROTR if it does not have ROTL.
+        StoreOp = DAG.getNode(ISD::ROTL, LoadDL, JointMemOpVT, NewLoad, RotAmt);
+      }
       NewStore = DAG.getStore(
-          NewStoreChain, StoreDL, NewLoad, FirstInChain->getBasePtr(),
+          NewStoreChain, StoreDL, StoreOp, FirstInChain->getBasePtr(),
           FirstInChain->getPointerInfo(), FirstStoreAlign, StMMOFlags);
     } else { // This must be the truncstore/extload case
       EVT ExtendedTy =
diff --git a/llvm/test/CodeGen/AArch64/merge-store-dependency.ll b/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
index 77b7012d2ed1e..6850846fec068 100644
--- a/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
+++ b/llvm/test/CodeGen/AArch64/merge-store-dependency.ll
@@ -95,6 +95,8 @@ exit:
   ret void
 }
 
+; TODO: rev16?
+
 define void @rotate16_in_place(i8* %p) {
 ; A53-LABEL: rotate16_in_place:
 ; A53:       // %bb.0:
@@ -112,6 +114,8 @@ define void @rotate16_in_place(i8* %p) {
   ret void
 }
 
+; TODO: rev16?
+
 define void @rotate16(i8* %p, i8* %q) {
 ; A53-LABEL: rotate16:
 ; A53:       // %bb.0:
@@ -134,10 +138,9 @@ define void @rotate16(i8* %p, i8* %q) {
 define void @rotate32_in_place(i16* %p) {
 ; A53-LABEL: rotate32_in_place:
 ; A53:       // %bb.0:
-; A53-NEXT:    ldrh w8, [x0, #2]
-; A53-NEXT:    ldrh w9, [x0]
-; A53-NEXT:    strh w8, [x0]
-; A53-NEXT:    strh w9, [x0, #2]
+; A53-NEXT:    ldr w8, [x0]
+; A53-NEXT:    ror w8, w8, #16
+; A53-NEXT:    str w8, [x0]
 ; A53-NEXT:    ret
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -151,10 +154,9 @@ define void @rotate32_in_place(i16* %p) {
 define void @rotate32(i16* %p) {
 ; A53-LABEL: rotate32:
 ; A53:       // %bb.0:
-; A53-NEXT:    ldrh w8, [x0, #2]
-; A53-NEXT:    ldrh w9, [x0]
-; A53-NEXT:    strh w8, [x0, #84]
-; A53-NEXT:    strh w9, [x0, #86]
+; A53-NEXT:    ldr w8, [x0]
+; A53-NEXT:    ror w8, w8, #16
+; A53-NEXT:    str w8, [x0, #84]
 ; A53-NEXT:    ret
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -167,6 +169,8 @@ define void @rotate32(i16* %p) {
   ret void
 }
 
+; Prefer paired memops over rotate.
+
 define void @rotate64_in_place(i32* %p) {
 ; A53-LABEL: rotate64_in_place:
 ; A53:       // %bb.0:
@@ -182,6 +186,8 @@ define void @rotate64_in_place(i32* %p) {
   ret void
 }
 
+; Prefer paired memops over rotate.
+
 define void @rotate64(i32* %p) {
 ; A53-LABEL: rotate64:
 ; A53:       // %bb.0:
diff --git a/llvm/test/CodeGen/X86/stores-merging.ll b/llvm/test/CodeGen/X86/stores-merging.ll
index 768684067f32f..60fd01eac0960 100644
--- a/llvm/test/CodeGen/X86/stores-merging.ll
+++ b/llvm/test/CodeGen/X86/stores-merging.ll
@@ -246,10 +246,7 @@ define void @pr43446_1(i8* %a) {
 define void @rotate16_in_place(i8* %p) {
 ; CHECK-LABEL: rotate16_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movb (%rdi), %al
-; CHECK-NEXT:    movb 1(%rdi), %cl
-; CHECK-NEXT:    movb %cl, (%rdi)
-; CHECK-NEXT:    movb %al, 1(%rdi)
+; CHECK-NEXT:    rolw $8, (%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i8, i8* %p, i64 0
   %p1 = getelementptr i8, i8* %p, i64 1
@@ -263,10 +260,9 @@ define void @rotate16_in_place(i8* %p) {
 define void @rotate16(i8* %p, i8* %q) {
 ; CHECK-LABEL: rotate16:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movb (%rdi), %al
-; CHECK-NEXT:    movb 1(%rdi), %cl
-; CHECK-NEXT:    movb %cl, (%rsi)
-; CHECK-NEXT:    movb %al, 1(%rsi)
+; CHECK-NEXT:    movzwl (%rdi), %eax
+; CHECK-NEXT:    rolw $8, %ax
+; CHECK-NEXT:    movw %ax, (%rsi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i8, i8* %p, i64 0
   %p1 = getelementptr i8, i8* %p, i64 1
@@ -282,10 +278,7 @@ define void @rotate16(i8* %p, i8* %q) {
 define void @rotate32_in_place(i16* %p) {
 ; CHECK-LABEL: rotate32_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movzwl (%rdi), %eax
-; CHECK-NEXT:    movzwl 2(%rdi), %ecx
-; CHECK-NEXT:    movw %cx, (%rdi)
-; CHECK-NEXT:    movw %ax, 2(%rdi)
+; CHECK-NEXT:    roll $16, (%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -299,10 +292,9 @@ define void @rotate32_in_place(i16* %p) {
 define void @rotate32(i16* %p) {
 ; CHECK-LABEL: rotate32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movzwl (%rdi), %eax
-; CHECK-NEXT:    movzwl 2(%rdi), %ecx
-; CHECK-NEXT:    movw %cx, 84(%rdi)
-; CHECK-NEXT:    movw %ax, 86(%rdi)
+; CHECK-NEXT:    movl (%rdi), %eax
+; CHECK-NEXT:    roll $16, %eax
+; CHECK-NEXT:    movl %eax, 84(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -318,10 +310,7 @@ define void @rotate32(i16* %p) {
 define void @rotate64_in_place(i32* %p) {
 ; CHECK-LABEL: rotate64_in_place:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl (%rdi), %eax
-; CHECK-NEXT:    movl 4(%rdi), %ecx
-; CHECK-NEXT:    movl %ecx, (%rdi)
-; CHECK-NEXT:    movl %eax, 4(%rdi)
+; CHECK-NEXT:    rolq $32, (%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i32, i32* %p, i64 0
   %p1 = getelementptr i32, i32* %p, i64 1
@@ -335,10 +324,9 @@ define void @rotate64_in_place(i32* %p) {
 define void @rotate64(i32* %p) {
 ; CHECK-LABEL: rotate64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl (%rdi), %eax
-; CHECK-NEXT:    movl 4(%rdi), %ecx
-; CHECK-NEXT:    movl %ecx, 8(%rdi)
-; CHECK-NEXT:    movl %eax, 12(%rdi)
+; CHECK-NEXT:    movq (%rdi), %rax
+; CHECK-NEXT:    rolq $32, %rax
+; CHECK-NEXT:    movq %rax, 8(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i32, i32* %p, i64 0
   %p1 = getelementptr i32, i32* %p, i64 1
@@ -354,10 +342,9 @@ define void @rotate64(i32* %p) {
 define void @rotate64_iterate(i16* %p) {
 ; CHECK-LABEL: rotate64_iterate:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movl (%rdi), %eax
-; CHECK-NEXT:    movl 4(%rdi), %ecx
-; CHECK-NEXT:    movl %ecx, 84(%rdi)
-; CHECK-NEXT:    movl %eax, 88(%rdi)
+; CHECK-NEXT:    movq (%rdi), %rax
+; CHECK-NEXT:    rolq $32, %rax
+; CHECK-NEXT:    movq %rax, 84(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1
@@ -378,6 +365,8 @@ define void @rotate64_iterate(i16* %p) {
   ret void
 }
 
+; TODO: recognize this as 2 rotates?
+
 define void @rotate32_consecutive(i16* %p) {
 ; CHECK-LABEL: rotate32_consecutive:
 ; CHECK:       # %bb.0:
@@ -409,17 +398,17 @@ define void @rotate32_consecutive(i16* %p) {
   ret void
 }
 
+; Same as above, but now the stores are not all consecutive.
+
 define void @rotate32_twice(i16* %p) {
 ; CHECK-LABEL: rotate32_twice:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    movzwl (%rdi), %eax
-; CHECK-NEXT:    movzwl 2(%rdi), %ecx
-; CHECK-NEXT:    movzwl 4(%rdi), %edx
-; CHECK-NEXT:    movzwl 6(%rdi), %esi
-; CHECK-NEXT:    movw %cx, 84(%rdi)
-; CHECK-NEXT:    movw %ax, 86(%rdi)
-; CHECK-NEXT:    movw %si, 108(%rdi)
-; CHECK-NEXT:    movw %dx, 110(%rdi)
+; CHECK-NEXT:    movl (%rdi), %eax
+; CHECK-NEXT:    movl 4(%rdi), %ecx
+; CHECK-NEXT:    roll $16, %eax
+; CHECK-NEXT:    roll $16, %ecx
+; CHECK-NEXT:    movl %eax, 84(%rdi)
+; CHECK-NEXT:    movl %ecx, 108(%rdi)
 ; CHECK-NEXT:    retq
   %p0 = getelementptr i16, i16* %p, i64 0
   %p1 = getelementptr i16, i16* %p, i64 1

From d7d1af39168ce8afd041f3ae8db1d1fd3d4f70ac Mon Sep 17 00:00:00 2001
From: Kirill Bobyrev 
Date: Mon, 13 Jul 2020 15:02:47 +0200
Subject: [PATCH 095/771] [clangd] Fix DocumentSymbol ranges

Summary:
DocumentSymbol ranges were not previously tested and, as a result, had invalid
end location. This patch addresses the issue.

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D83668
---
 clang-tools-extra/clangd/FindSymbols.cpp      | 16 ++---
 .../clangd/unittests/FindSymbolsTests.cpp     | 68 ++++++++++++++++++-
 2 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp
index 58e2ee1e21c77..f5d6a95aa713d 100644
--- a/clang-tools-extra/clangd/FindSymbols.cpp
+++ b/clang-tools-extra/clangd/FindSymbols.cpp
@@ -136,17 +136,11 @@ llvm::Optional declToSym(ASTContext &Ctx, const NamedDecl &ND) {
   auto &SM = Ctx.getSourceManager();
 
   SourceLocation NameLoc = nameLocation(ND, SM);
-  // getFileLoc is a good choice for us, but we also need to make sure
-  // sourceLocToPosition won't switch files, so we call getSpellingLoc on top of
-  // that to make sure it does not switch files.
-  // FIXME: sourceLocToPosition should not switch files!
   SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
   SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
-  if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid())
-    return llvm::None;
-
-  if (!SM.isWrittenInMainFile(NameLoc) || !SM.isWrittenInMainFile(BeginLoc) ||
-      !SM.isWrittenInMainFile(EndLoc))
+  const auto SymbolRange =
+      toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc});
+  if (!SymbolRange)
     return llvm::None;
 
   Position NameBegin = sourceLocToPosition(SM, NameLoc);
@@ -162,8 +156,8 @@ llvm::Optional declToSym(ASTContext &Ctx, const NamedDecl &ND) {
   SI.name = printName(Ctx, ND);
   SI.kind = SK;
   SI.deprecated = ND.isDeprecated();
-  SI.range =
-      Range{sourceLocToPosition(SM, BeginLoc), sourceLocToPosition(SM, EndLoc)};
+  SI.range = Range{sourceLocToPosition(SM, SymbolRange->getBegin()),
+                   sourceLocToPosition(SM, SymbolRange->getEnd())};
   SI.selectionRange = Range{NameBegin, NameEnd};
   if (!SI.range.contains(SI.selectionRange)) {
     // 'selectionRange' must be contained in 'range', so in cases where clang
diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
index 31879e356ce0e..07c42fcf20304 100644
--- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
@@ -35,7 +35,7 @@ MATCHER_P(QName, Name, "") {
 }
 MATCHER_P(WithName, N, "") { return arg.name == N; }
 MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; }
-MATCHER_P(SymRange, Range, "") { return arg.location.range == Range; }
+MATCHER_P(SymRange, Range, "") { return arg.range == Range; }
 
 // GMock helpers for matching DocumentSymbol.
 MATCHER_P(SymNameRange, Range, "") { return arg.selectionRange == Range; }
@@ -712,6 +712,72 @@ TEST(DocumentSymbols, QualifiersWithTemplateArgs) {
                            WithName("Foo_type::method3")));
 }
 
+TEST(DocumentSymbolsTest, Ranges) {
+  TestTU TU;
+  Annotations Main(R"(
+      $foo[[int foo(bool Argument) {
+        return 42;
+      }]]
+
+      $variable[[char GLOBAL_VARIABLE]];
+
+      $ns[[namespace ns {
+      $bar[[class Bar {
+      public:
+        $ctor[[Bar() {}]]
+        $dtor[[~Bar()]];
+
+      private:
+        $field[[unsigned Baz]];
+
+        $getbaz[[unsigned getBaz() { return Baz; }]]
+      }]];
+      }]] // namespace ns
+
+      $forwardclass[[class ForwardClassDecl]];
+
+      $struct[[struct StructDefinition {
+        $structfield[[int *Pointer = nullptr]];
+      }]];
+      $forwardstruct[[struct StructDeclaration]];
+
+      $forwardfunc[[void forwardFunctionDecl(int Something)]];
+    )");
+  TU.Code = Main.code().str();
+  EXPECT_THAT(
+      getSymbols(TU.build()),
+      UnorderedElementsAre(
+          AllOf(WithName("foo"), WithKind(SymbolKind::Function),
+                SymRange(Main.range("foo"))),
+          AllOf(WithName("GLOBAL_VARIABLE"), WithKind(SymbolKind::Variable),
+                SymRange(Main.range("variable"))),
+          AllOf(
+              WithName("ns"), WithKind(SymbolKind::Namespace),
+              SymRange(Main.range("ns")),
+              Children(AllOf(
+                  WithName("Bar"), WithKind(SymbolKind::Class),
+                  SymRange(Main.range("bar")),
+                  Children(
+                      AllOf(WithName("Bar"), WithKind(SymbolKind::Constructor),
+                            SymRange(Main.range("ctor"))),
+                      AllOf(WithName("~Bar"), WithKind(SymbolKind::Constructor),
+                            SymRange(Main.range("dtor"))),
+                      AllOf(WithName("Baz"), WithKind(SymbolKind::Field),
+                            SymRange(Main.range("field"))),
+                      AllOf(WithName("getBaz"), WithKind(SymbolKind::Method),
+                            SymRange(Main.range("getbaz"))))))),
+          AllOf(WithName("ForwardClassDecl"), WithKind(SymbolKind::Class),
+                SymRange(Main.range("forwardclass"))),
+          AllOf(WithName("StructDefinition"), WithKind(SymbolKind::Struct),
+                SymRange(Main.range("struct")),
+                Children(AllOf(WithName("Pointer"), WithKind(SymbolKind::Field),
+                               SymRange(Main.range("structfield"))))),
+          AllOf(WithName("StructDeclaration"), WithKind(SymbolKind::Struct),
+                SymRange(Main.range("forwardstruct"))),
+          AllOf(WithName("forwardFunctionDecl"), WithKind(SymbolKind::Function),
+                SymRange(Main.range("forwardfunc")))));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang

From f3b3689c043f49ad42e9d3f5057bc8f1a9f56d09 Mon Sep 17 00:00:00 2001
From: Raphael Isemann 
Date: Mon, 13 Jul 2020 13:36:25 +0200
Subject: [PATCH 096/771] [lldb][NFC] Refactor instruction dumping out of
 DumpDataExtractor

---
 lldb/source/Core/DumpDataExtractor.cpp | 88 +++++++++++++++-----------
 1 file changed, 50 insertions(+), 38 deletions(-)

diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp
index 233a1b3735508..33fc3a76d3d67 100644
--- a/lldb/source/Core/DumpDataExtractor.cpp
+++ b/lldb/source/Core/DumpDataExtractor.cpp
@@ -128,6 +128,53 @@ static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data,
   return offset;
 }
 
+/// Dumps decoded instructions to a stream.
+static lldb::offset_t DumpInstructions(const DataExtractor &DE, Stream *s,
+                                       ExecutionContextScope *exe_scope,
+                                       offset_t start_offset,
+                                       uint64_t base_addr,
+                                       size_t number_of_instructions) {
+  offset_t offset = start_offset;
+
+  TargetSP target_sp;
+  if (exe_scope)
+    target_sp = exe_scope->CalculateTarget();
+  if (target_sp) {
+    DisassemblerSP disassembler_sp(
+        Disassembler::FindPlugin(target_sp->GetArchitecture(),
+                                 target_sp->GetDisassemblyFlavor(), nullptr));
+    if (disassembler_sp) {
+      lldb::addr_t addr = base_addr + start_offset;
+      lldb_private::Address so_addr;
+      bool data_from_file = true;
+      if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
+        data_from_file = false;
+      } else {
+        if (target_sp->GetSectionLoadList().IsEmpty() ||
+            !target_sp->GetImages().ResolveFileAddress(addr, so_addr))
+          so_addr.SetRawAddress(addr);
+      }
+
+      size_t bytes_consumed = disassembler_sp->DecodeInstructions(
+          so_addr, DE, start_offset, number_of_instructions, false,
+          data_from_file);
+
+      if (bytes_consumed) {
+        offset += bytes_consumed;
+        const bool show_address = base_addr != LLDB_INVALID_ADDRESS;
+        const bool show_bytes = true;
+        ExecutionContext exe_ctx;
+        exe_scope->CalculateExecutionContext(exe_ctx);
+        disassembler_sp->GetInstructionList().Dump(s, show_address, show_bytes,
+                                                   &exe_ctx);
+      }
+    }
+  } else
+    s->Printf("invalid target");
+
+  return offset;
+}
+
 lldb::offset_t lldb_private::DumpDataExtractor(
     const DataExtractor &DE, Stream *s, offset_t start_offset,
     lldb::Format item_format, size_t item_byte_size, size_t item_count,
@@ -147,44 +194,9 @@ lldb::offset_t lldb_private::DumpDataExtractor(
 
   offset_t offset = start_offset;
 
-  if (item_format == eFormatInstruction) {
-    TargetSP target_sp;
-    if (exe_scope)
-      target_sp = exe_scope->CalculateTarget();
-    if (target_sp) {
-      DisassemblerSP disassembler_sp(Disassembler::FindPlugin(
-          target_sp->GetArchitecture(),
-          target_sp->GetDisassemblyFlavor(), nullptr));
-      if (disassembler_sp) {
-        lldb::addr_t addr = base_addr + start_offset;
-        lldb_private::Address so_addr;
-        bool data_from_file = true;
-        if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) {
-          data_from_file = false;
-        } else {
-          if (target_sp->GetSectionLoadList().IsEmpty() ||
-              !target_sp->GetImages().ResolveFileAddress(addr, so_addr))
-            so_addr.SetRawAddress(addr);
-        }
-
-        size_t bytes_consumed = disassembler_sp->DecodeInstructions(
-            so_addr, DE, start_offset, item_count, false, data_from_file);
-
-        if (bytes_consumed) {
-          offset += bytes_consumed;
-          const bool show_address = base_addr != LLDB_INVALID_ADDRESS;
-          const bool show_bytes = true;
-          ExecutionContext exe_ctx;
-          exe_scope->CalculateExecutionContext(exe_ctx);
-          disassembler_sp->GetInstructionList().Dump(s, show_address,
-                                                     show_bytes, &exe_ctx);
-        }
-      }
-    } else
-      s->Printf("invalid target");
-
-    return offset;
-  }
+  if (item_format == eFormatInstruction)
+    return DumpInstructions(DE, s, exe_scope, start_offset, base_addr,
+                            item_count);
 
   if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) &&
       item_byte_size > 8)

From 725412f1f54aca6d465b61191b420c0aee0cef38 Mon Sep 17 00:00:00 2001
From: Georgii Rymar 
Date: Thu, 9 Jul 2020 16:03:40 +0300
Subject: [PATCH 097/771] [yaml2obj] - Refactor header-sh-fields.yaml test.

This refines the test to use macros. It is needed for
a follow-up change that adds a functionality to
override more fields.

Also, it is just cleaner to test each key separately.

Differential revision: https://reviews.llvm.org/D83481
---
 .../tools/yaml2obj/ELF/header-sh-fields.yaml  | 64 ++++++++++---------
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml b/llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml
index 821b77418857c..166c68405bb76 100644
--- a/llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/header-sh-fields.yaml
@@ -3,8 +3,8 @@
 
 ## First we check the default values.
 
-# RUN: yaml2obj --docnum=1 %s -o %t1
-# RUN: llvm-readelf --file-headers %t1 | FileCheck %s --check-prefix=DEFAULT
+# RUN: yaml2obj %s -o %t-default
+# RUN: llvm-readelf --file-headers %t-default | FileCheck %s --check-prefix=DEFAULT
 
 # DEFAULT:   Start of section headers:          88 (bytes into file)
 # DEFAULT:   Size of section headers:           64 (bytes)
@@ -18,15 +18,10 @@ FileHeader:
   Type:    ET_REL
   Machine: EM_X86_64
 
-## Override 3 fields: e_shoff, e_shnum and e_shstrndx. Check the output.
-
-# RUN: yaml2obj --docnum=2 %s -o %t2
-# RUN: llvm-readelf --file-headers %t2 | FileCheck %s --check-prefix=CUSTOM
-
-# CUSTOM: Start of section headers:          2 (bytes into file)
-# CUSTOM: Size of section headers:           64 (bytes)
-# CUSTOM: Number of section headers:         3
-# CUSTOM: Section header string table index: 4
+## Check we can override all default values using the same values
+## and that this does not change the output.
+# RUN: yaml2obj --docnum=2 %s -o %t-default-override
+# RUN: cmp %t-default %t-default-override
 
 --- !ELF
 FileHeader:
@@ -34,28 +29,37 @@ FileHeader:
   Data:      ELFDATA2LSB
   Type:      ET_REL
   Machine:   EM_X86_64
-  SHEntSize: 64
-  SHOff:     2
-  SHNum:     3
-  SHStrNdx:  4
+  SHEntSize: [[SHENTSIZE=64]]
+  SHOff:     [[SHOFF=88]]
+  SHNum:     [[SHNUM=3]]
+  SHStrNdx:  [[SHSTRNDX=2]]
+
+## Override different fields to check the output produced.
+
+## Override the e_shoff field.
+# RUN: yaml2obj --docnum=2 %s -DSHOFF=3 -o %t2
+# RUN: llvm-readelf --file-headers %t2 | FileCheck %s --check-prefix=SHOFF
+
+# SHOFF: Start of section headers: 3 (bytes into file)
+
+## Override the e_shnum field.
+# RUN: yaml2obj --docnum=2 %s -DSHNUM=2 -o %t3
+# RUN: llvm-readelf --file-headers %t3 | FileCheck %s --check-prefix=SHNUM
+
+# SHNUM: Number of section headers: 2{{$}}
+
+## Override the e_shstrndx field.
+# RUN: yaml2obj --docnum=2 %s -DSHSTRNDX=4 -o %t4
+# RUN: llvm-readelf --file-headers %t4 | FileCheck %s --check-prefix=SHSTRNDX
 
-## Finally, we use the same YAML as above, but set e_shentsize to 1.
+# SHSTRNDX: Section header string table index: 4{{$}}
+
+## Override the e_shentsize field.
 ## Check the result using raw output from 'od' because llvm-readelf
 ## is unable to dump such headers.
 
-# RUN: yaml2obj --docnum=3 %s -o %t3
-# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t3 | FileCheck %s --check-prefix=NEWSIZE
-# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t2 | FileCheck %s --check-prefix=OLDSIZE
+# RUN: yaml2obj --docnum=2 %s -DSHENTSIZE=1 -o %t5
+# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t5 | FileCheck %s --check-prefix=NEWSIZE
+# RUN: od -A n -t x1 -v -j 0x3a -N 1 %t-default | FileCheck %s --check-prefix=OLDSIZE
 # NEWSIZE: 01
 # OLDSIZE: 40
-
---- !ELF
-FileHeader:
-  Class:     ELFCLASS64
-  Data:      ELFDATA2LSB
-  Type:      ET_REL
-  Machine:   EM_X86_64
-  SHEntSize: 1
-  SHOff:     2
-  SHNum:     3
-  SHStrNdx:  4

From 2e58004fe1873825cce772113f96339eecc0bb3a Mon Sep 17 00:00:00 2001
From: Sanne Wouda 
Date: Thu, 25 Jun 2020 16:08:13 +0100
Subject: [PATCH 098/771] Fix crash when getVFABIMappings is called with an
 indirect call instruction

Differential Revision: https://reviews.llvm.org/D83122
---
 llvm/include/llvm/Analysis/VectorUtils.h      |  3 +++
 .../Analysis/VectorFunctionABITest.cpp        | 26 +++++++++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index 9acb1fcf11029..ce8327ae43a80 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -224,6 +224,9 @@ class VFDatabase {
   /// a vector Function ABI.
   static void getVFABIMappings(const CallInst &CI,
                                SmallVectorImpl &Mappings) {
+    if (CI.isIndirectCall())
+      return;
+
     const StringRef ScalarName = CI.getCalledFunction()->getName();
 
     SmallVector ListOfStrings;
diff --git a/llvm/unittests/Analysis/VectorFunctionABITest.cpp b/llvm/unittests/Analysis/VectorFunctionABITest.cpp
index 6668529f49e09..d1f878754cbba 100644
--- a/llvm/unittests/Analysis/VectorFunctionABITest.cpp
+++ b/llvm/unittests/Analysis/VectorFunctionABITest.cpp
@@ -618,3 +618,29 @@ TEST_F(VFABIParserTest, ZeroIsInvalidVLEN) {
   EXPECT_FALSE(invokeParser("_ZGVsM0v_sin"));
   EXPECT_FALSE(invokeParser("_ZGVsN0v_sin"));
 }
+
+static std::unique_ptr parseIR(LLVMContext &C, const char *IR) {
+  SMDiagnostic Err;
+  std::unique_ptr Mod = parseAssemblyString(IR, Err, C);
+  if (!Mod)
+    Err.print("VectorFunctionABITests", errs());
+  return Mod;
+}
+
+TEST(VFABIGetMappingsTest, IndirectCallInst) {
+  LLVMContext C;
+  std::unique_ptr M = parseIR(C, R"IR(
+define void @call(void () * %f) {
+entry:
+  call void %f()
+  ret void
+}
+)IR");
+  auto F = dyn_cast_or_null(M->getNamedValue("call"));
+  ASSERT_TRUE(F);
+  auto CI = dyn_cast(&F->front().front());
+  ASSERT_TRUE(CI);
+  ASSERT_TRUE(CI->isIndirectCall());
+  auto Mappings = VFDatabase::getMappings(*CI);
+  EXPECT_EQ(Mappings.size(), (unsigned)0);
+}

From e909f6bc48ee291f4be0d69a5eb0b80b96f7d16e Mon Sep 17 00:00:00 2001
From: Sanne Wouda 
Date: Thu, 25 Jun 2020 16:02:52 +0100
Subject: [PATCH 099/771] Pre-commit tests

Prepare to land D82550
---
 .../AArch64/accelerate-vector-functions.ll    | 1213 ++++++++++++++++-
 .../SLPVectorizer/vectorizable-functions.ll   |   81 ++
 2 files changed, 1266 insertions(+), 28 deletions(-)
 create mode 100644 llvm/test/Transforms/SLPVectorizer/vectorizable-functions.ll

diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/accelerate-vector-functions.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/accelerate-vector-functions.ll
index 0adc695a13417..1cd93d20f85e8 100644
--- a/llvm/test/Transforms/SLPVectorizer/AArch64/accelerate-vector-functions.ll
+++ b/llvm/test/Transforms/SLPVectorizer/AArch64/accelerate-vector-functions.ll
@@ -5,55 +5,1212 @@
 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
 target triple = "arm64-apple-ios14.0.0"
 
-declare float @llvm.sin.f32(float) #1
-
+declare float @llvm.sin.f32(float)
 
 ; Accelerate provides sin() for <4 x float>
+define <4 x float> @int_sin_4x(<4 x float>* %a) {
+; CHECK-LABEL: @int_sin_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vsinf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @int_sin_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @llvm.sin.f32(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @llvm.sin.f32(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @llvm.sin.f32(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @llvm.sin.f32(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+
+declare float @ceilf(float) readonly
+
+define <4 x float> @ceil_4x(<4 x float>* %a) {
+; CHECK-LABEL: @ceil_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.ceil.v4f32(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @ceil_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.ceil.v4f32(<4 x float> [[TMP0]])
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; NOACCELERATE-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @ceilf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @ceilf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @ceilf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @ceilf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+
+declare float @fabsf(float) readonly
+
+define <4 x float> @fabs_4x(<4 x float>* %a) {
+; CHECK-LABEL: @fabs_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @fabs_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP0]])
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; NOACCELERATE-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @fabsf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @fabsf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @fabsf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @fabsf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @llvm.fabs.f32(float)
+define <4 x float> @int_fabs_4x(<4 x float>* %a) {
+; CHECK-LABEL: @int_fabs_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @int_fabs_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.fabs.v4f32(<4 x float> [[TMP0]])
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; NOACCELERATE-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @llvm.fabs.f32(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @llvm.fabs.f32(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @llvm.fabs.f32(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @llvm.fabs.f32(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @floorf(float) readonly
+define <4 x float> @floor_4x(<4 x float>* %a) {
+; CHECK-LABEL: @floor_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.floor.v4f32(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @floor_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.floor.v4f32(<4 x float> [[TMP0]])
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; NOACCELERATE-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @floorf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @floorf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @floorf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @floorf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @sqrtf(float) readonly
+define <4 x float> @sqrt_4x(<4 x float>* %a) {
+; CHECK-LABEL: @sqrt_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.sqrt.v4f32(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @sqrt_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @llvm.sqrt.v4f32(<4 x float> [[TMP0]])
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; NOACCELERATE-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @sqrtf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @sqrtf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @sqrtf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @sqrtf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @expf(float) readonly
+define <4 x float> @exp_4x(<4 x float>* %a) {
+; CHECK-LABEL: @exp_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vexpf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @exp_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @expf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @expf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @expf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @expf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @expf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @expf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @expf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @expf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @expm1f(float) readonly
+define <4 x float> @expm1_4x(<4 x float>* %a) {
+; CHECK-LABEL: @expm1_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @expm1f(float [[VECEXT]]) #2
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @expm1f(float [[VECEXT_1]]) #2
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @expm1f(float [[VECEXT_2]]) #2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @expm1f(float [[VECEXT_3]]) #2
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @expm1_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @expm1f(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @expm1f(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @expm1f(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @expm1f(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @expm1f(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @expm1f(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @expm1f(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @expm1f(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @logf(float) readonly
+define <4 x float> @log_4x(<4 x float>* %a) {
+; CHECK-LABEL: @log_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vlogf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @log_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @logf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @logf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @logf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @logf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @logf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @logf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @logf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @logf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @log1pf(float) readonly
+define <4 x float> @log1p_4x(<4 x float>* %a) {
+; CHECK-LABEL: @log1p_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @log1pf(float [[VECEXT]]) #3
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @log1pf(float [[VECEXT_1]]) #3
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @log1pf(float [[VECEXT_2]]) #3
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @log1pf(float [[VECEXT_3]]) #3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @log1p_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @log1pf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @log1pf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @log1pf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @log1pf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @log1pf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @log1pf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @log1pf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @log1pf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @log10pf(float) readonly
+define <4 x float> @log10p_4x(<4 x float>* %a) {
+; CHECK-LABEL: @log10p_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @log10pf(float [[VECEXT]])
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @log10pf(float [[VECEXT_1]])
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @log10pf(float [[VECEXT_2]])
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @log10pf(float [[VECEXT_3]])
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @log10p_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @log10pf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @log10pf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @log10pf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @log10pf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @log10pf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @log10pf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @log10pf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @log10pf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @logbf(float) readonly
+define <4 x float> @logb_4x(<4 x float>* %a) {
+; CHECK-LABEL: @logb_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @logbf(float [[VECEXT]]) #4
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @logbf(float [[VECEXT_1]]) #4
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @logbf(float [[VECEXT_2]]) #4
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @logbf(float [[VECEXT_3]]) #4
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @logb_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @logbf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @logbf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @logbf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @logbf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @logbf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @logbf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @logbf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @logbf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @sinf(float) readonly
 define <4 x float> @sin_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @sin_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vsinf(<4 x float> [[TMP0]])
-; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
-; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
-; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
-; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vsinf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @sin_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @sinf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @sinf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @sinf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @sinf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @sinf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @sinf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @sinf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @sinf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @cosf(float) readonly
+define <4 x float> @cos_4x(<4 x float>* %a) {
+; CHECK-LABEL: @cos_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vcosf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @cos_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @cosf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @cosf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @cosf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @cosf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @cosf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @cosf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @cosf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @cosf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @tanf(float) readonly
+define <4 x float> @tan_4x(<4 x float>* %a) {
+; CHECK-LABEL: @tan_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @tanf(float [[VECEXT]]) #5
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @tanf(float [[VECEXT_1]]) #5
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @tanf(float [[VECEXT_2]]) #5
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @tanf(float [[VECEXT_3]]) #5
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @tan_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @tanf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @tanf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @tanf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @tanf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @tanf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @tanf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @tanf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @tanf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @asinf(float) readonly
+define <4 x float> @asin_4x(<4 x float>* %a) {
+; CHECK-LABEL: @asin_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @asinf(float [[VECEXT]]) #6
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @asinf(float [[VECEXT_1]]) #6
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @asinf(float [[VECEXT_2]]) #6
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @asinf(float [[VECEXT_3]]) #6
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
-; NOACCELERATE-LABEL: @sin_4x(
+; NOACCELERATE-LABEL: @asin_4x(
 ; NOACCELERATE-NEXT:  entry:
 ; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
 ; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @asinf(float [[VECEXT]])
 ; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
 ; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @asinf(float [[VECEXT_1]])
 ; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
 ; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @asinf(float [[VECEXT_2]])
 ; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
 ; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @asinf(float [[VECEXT_3]])
 ; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
 ; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 entry:
   %0 = load <4 x float>, <4 x float>* %a, align 16
   %vecext = extractelement <4 x float> %0, i32 0
-  %1 = tail call fast float @llvm.sin.f32(float %vecext)
+  %1 = tail call fast float @asinf(float %vecext)
   %vecins = insertelement <4 x float> undef, float %1, i32 0
   %vecext.1 = extractelement <4 x float> %0, i32 1
-  %2 = tail call fast float @llvm.sin.f32(float %vecext.1)
+  %2 = tail call fast float @asinf(float %vecext.1)
   %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
   %vecext.2 = extractelement <4 x float> %0, i32 2
-  %3 = tail call fast float @llvm.sin.f32(float %vecext.2)
+  %3 = tail call fast float @asinf(float %vecext.2)
   %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
   %vecext.3 = extractelement <4 x float> %0, i32 3
-  %4 = tail call fast float @llvm.sin.f32(float %vecext.3)
+  %4 = tail call fast float @asinf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @acosf(float) readonly
+define <4 x float> @acos_4x(<4 x float>* %a) {
+; CHECK-LABEL: @acos_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @acosf(float [[VECEXT]]) #7
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @acosf(float [[VECEXT_1]]) #7
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @acosf(float [[VECEXT_2]]) #7
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @acosf(float [[VECEXT_3]]) #7
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @acos_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @acosf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @acosf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @acosf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @acosf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @acosf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @acosf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @acosf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @acosf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @atanf(float) readonly
+define <4 x float> @atan_4x(<4 x float>* %a) {
+; CHECK-LABEL: @atan_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @atanf(float [[VECEXT]]) #8
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @atanf(float [[VECEXT_1]]) #8
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @atanf(float [[VECEXT_2]]) #8
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @atanf(float [[VECEXT_3]]) #8
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @atan_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @atanf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @atanf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @atanf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @atanf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @atanf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @atanf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @atanf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @atanf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @sinhf(float) readonly
+define <4 x float> @sinh_4x(<4 x float>* %a) {
+; CHECK-LABEL: @sinh_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @sinhf(float [[VECEXT]]) #9
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @sinhf(float [[VECEXT_1]]) #9
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @sinhf(float [[VECEXT_2]]) #9
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @sinhf(float [[VECEXT_3]]) #9
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @sinh_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @sinhf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @sinhf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @sinhf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @sinhf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @sinhf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @sinhf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @sinhf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @sinhf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @coshf(float) readonly
+define <4 x float> @cosh_4x(<4 x float>* %a) {
+; CHECK-LABEL: @cosh_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @coshf(float [[VECEXT]]) #10
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @coshf(float [[VECEXT_1]]) #10
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @coshf(float [[VECEXT_2]]) #10
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @coshf(float [[VECEXT_3]]) #10
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @cosh_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @coshf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @coshf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @coshf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @coshf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @coshf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @coshf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @coshf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @coshf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @tanhf(float) readonly
+define <4 x float> @tanh_4x(<4 x float>* %a) {
+; CHECK-LABEL: @tanh_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @tanhf(float [[VECEXT]]) #11
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @tanhf(float [[VECEXT_1]]) #11
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @tanhf(float [[VECEXT_2]]) #11
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @tanhf(float [[VECEXT_3]]) #11
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @tanh_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @tanhf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @tanhf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @tanhf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @tanhf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @tanhf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @tanhf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @tanhf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @tanhf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @asinhf(float) readonly
+define <4 x float> @asinh_4x(<4 x float>* %a) {
+; CHECK-LABEL: @asinh_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @asinhf(float [[VECEXT]]) #12
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @asinhf(float [[VECEXT_1]]) #12
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @asinhf(float [[VECEXT_2]]) #12
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @asinhf(float [[VECEXT_3]]) #12
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @asinh_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @asinhf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @asinhf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @asinhf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @asinhf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @asinhf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @asinhf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @asinhf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @asinhf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @acoshf(float) readonly
+define <4 x float> @acosh_4x(<4 x float>* %a) {
+; CHECK-LABEL: @acosh_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @acoshf(float [[VECEXT]]) #13
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @acoshf(float [[VECEXT_1]]) #13
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @acoshf(float [[VECEXT_2]]) #13
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @acoshf(float [[VECEXT_3]]) #13
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @acosh_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @acoshf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @acoshf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @acoshf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @acoshf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @acoshf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @acoshf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @acoshf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @acoshf(float %vecext.3)
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+declare float @atanhf(float) readonly
+define <4 x float> @atanh_4x(<4 x float>* %a) {
+; CHECK-LABEL: @atanh_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @atanhf(float [[VECEXT]]) #14
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @atanhf(float [[VECEXT_1]]) #14
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @atanhf(float [[VECEXT_2]]) #14
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @atanhf(float [[VECEXT_3]]) #14
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+; NOACCELERATE-LABEL: @atanh_4x(
+; NOACCELERATE-NEXT:  entry:
+; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; NOACCELERATE-NEXT:    [[TMP1:%.*]] = tail call fast float @atanhf(float [[VECEXT]])
+; NOACCELERATE-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; NOACCELERATE-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; NOACCELERATE-NEXT:    [[TMP2:%.*]] = tail call fast float @atanhf(float [[VECEXT_1]])
+; NOACCELERATE-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; NOACCELERATE-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; NOACCELERATE-NEXT:    [[TMP3:%.*]] = tail call fast float @atanhf(float [[VECEXT_2]])
+; NOACCELERATE-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; NOACCELERATE-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; NOACCELERATE-NEXT:    [[TMP4:%.*]] = tail call fast float @atanhf(float [[VECEXT_3]])
+; NOACCELERATE-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; NOACCELERATE-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @atanhf(float %vecext)
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @atanhf(float %vecext.1)
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @atanhf(float %vecext.2)
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @atanhf(float %vecext.3)
   %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
   ret <4 x float> %vecins.3
 }
@@ -64,10 +1221,10 @@ define <2 x float> @sin_2x(<2 x float>* %a) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x float>, <2 x float>* [[A:%.*]], align 16
 ; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <2 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT]]) #1
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT]]) #15
 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <2 x float> undef, float [[TMP1]], i32 0
 ; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <2 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_1]]) #1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_1]]) #15
 ; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <2 x float> [[VECINS]], float [[TMP2]], i32 1
 ; CHECK-NEXT:    ret <2 x float> [[VECINS_1]]
 ;
@@ -94,11 +1251,11 @@ entry:
 }
 
 
-declare float @llvm.cos.f32(float) #1
+declare float @llvm.cos.f32(float)
 
 ; Accelerate provides cos() for <4 x float>
-define <4 x float> @cos_4x(<4 x float>* %a) {
-; CHECK-LABEL: @cos_4x(
+define <4 x float> @int_cos_4x(<4 x float>* %a) {
+; CHECK-LABEL: @int_cos_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
 ; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vcosf(<4 x float> [[TMP0]])
@@ -112,7 +1269,7 @@ define <4 x float> @cos_4x(<4 x float>* %a) {
 ; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
-; NOACCELERATE-LABEL: @cos_4x(
+; NOACCELERATE-LABEL: @int_cos_4x(
 ; NOACCELERATE-NEXT:  entry:
 ; NOACCELERATE-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
 ; NOACCELERATE-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
@@ -152,10 +1309,10 @@ define <2 x float> @cos_2x(<2 x float>* %a) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x float>, <2 x float>* [[A:%.*]], align 16
 ; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <2 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.cos.f32(float [[VECEXT]]) #2
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.cos.f32(float [[VECEXT]]) #16
 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <2 x float> undef, float [[TMP1]], i32 0
 ; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <2 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.cos.f32(float [[VECEXT_1]]) #2
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.cos.f32(float [[VECEXT_1]]) #16
 ; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <2 x float> [[VECINS]], float [[TMP2]], i32 1
 ; CHECK-NEXT:    ret <2 x float> [[VECINS_1]]
 ;
diff --git a/llvm/test/Transforms/SLPVectorizer/vectorizable-functions.ll b/llvm/test/Transforms/SLPVectorizer/vectorizable-functions.ll
new file mode 100644
index 0000000000000..bb27efbf424ec
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/vectorizable-functions.ll
@@ -0,0 +1,81 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -slp-vectorizer -S %s | FileCheck %s
+
+declare float @memread(float) readonly #0
+declare <4 x float> @vmemread(<4 x float>)
+
+define <4 x float> @memread_4x(<4 x float>* %a) {
+; CHECK-LABEL: @memread_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @memread(float [[VECEXT]]) #2
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @memread(float [[VECEXT_1]]) #2
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @memread(float [[VECEXT_2]]) #2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @memread(float [[VECEXT_3]]) #2
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @memread(float %vecext) #0
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @memread(float %vecext.1) #0
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @memread(float %vecext.2) #0
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @memread(float %vecext.3) #0
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+
+declare float @memwrite(float) #1
+declare <4 x float> @vmemwrite(<4 x float>)
+
+define <4 x float> @memwrite_4x(<4 x float>* %a) {
+; CHECK-LABEL: @memwrite_4x(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
+; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @memwrite(float [[VECEXT]]) #1
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @memwrite(float [[VECEXT_1]]) #1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
+; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @memwrite(float [[VECEXT_2]]) #1
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
+; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @memwrite(float [[VECEXT_3]]) #1
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
+;
+entry:
+  %0 = load <4 x float>, <4 x float>* %a, align 16
+  %vecext = extractelement <4 x float> %0, i32 0
+  %1 = tail call fast float @memwrite(float %vecext) #1
+  %vecins = insertelement <4 x float> undef, float %1, i32 0
+  %vecext.1 = extractelement <4 x float> %0, i32 1
+  %2 = tail call fast float @memwrite(float %vecext.1) #1
+  %vecins.1 = insertelement <4 x float> %vecins, float %2, i32 1
+  %vecext.2 = extractelement <4 x float> %0, i32 2
+  %3 = tail call fast float @memwrite(float %vecext.2) #1
+  %vecins.2 = insertelement <4 x float> %vecins.1, float %3, i32 2
+  %vecext.3 = extractelement <4 x float> %0, i32 3
+  %4 = tail call fast float @memwrite(float %vecext.3) #1
+  %vecins.3 = insertelement <4 x float> %vecins.2, float %4, i32 3
+  ret <4 x float> %vecins.3
+}
+
+attributes #0 = { "vector-function-abi-variant"="_ZGV_LLVM_N4v_memread(vmemread)" }
+attributes #1 = { "vector-function-abi-variant"="_ZGV_LLVM_N4v_memwrite(vmemwrite)" }

From 7b84045565bdf7945a2cddd4dd7eefa00fb220d3 Mon Sep 17 00:00:00 2001
From: Sanne Wouda 
Date: Fri, 10 Jul 2020 12:37:26 +0100
Subject: [PATCH 100/771] [SLPVectorizer] handle vectorizeable library
 functions

Teaches the SLPVectorizer to use vectorized library functions for
non-intrinsic calls.

This already worked for intrinsics that have vectorized library
functions, thanks to D75878, but schedules with library functions with a
vector variant were being rejected early.

-   assume that there are no load/store dependencies between lib
    functions with a vector variant; this would otherwise prevent the
    bundle from becoming "ready"

-   check during legalization that the vector variant can be used

-   fix-up where we previously assumed that a call would be an intrinsic

Differential Revision: https://reviews.llvm.org/D82550
---
 .../Transforms/Vectorize/SLPVectorizer.cpp    |  27 +-
 .../AArch64/accelerate-vector-functions.ll    | 281 ++++++++----------
 .../SLPVectorizer/vectorizable-functions.ll   |  21 +-
 3 files changed, 148 insertions(+), 181 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index d4b16fac985d9..fe9ea2995377c 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -3022,12 +3022,17 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth,
       return;
     }
     case Instruction::Call: {
-      // Check if the calls are all to the same vectorizable intrinsic.
+      // Check if the calls are all to the same vectorizable intrinsic or
+      // library function.
       CallInst *CI = cast(VL0);
-      // Check if this is an Intrinsic call or something that can be
-      // represented by an intrinsic call
       Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
-      if (!isTriviallyVectorizable(ID)) {
+
+      VFShape Shape = VFShape::get(
+          *CI, {static_cast(VL.size()), false /*Scalable*/},
+          false /*HasGlobalPred*/);
+      Function *VecFunc = VFDatabase(*CI).getVectorizedFunction(Shape);
+
+      if (!VecFunc && !isTriviallyVectorizable(ID)) {
         BS.cancelScheduling(VL, VL0);
         newTreeEntry(VL, None /*not vectorized*/, S, UserTreeIdx,
                      ReuseShuffleIndicies);
@@ -3044,6 +3049,8 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth,
         CallInst *CI2 = dyn_cast(V);
         if (!CI2 || CI2->getCalledFunction() != Int ||
             getVectorIntrinsicIDForCall(CI2, TLI) != ID ||
+            (VecFunc &&
+             VecFunc != VFDatabase(*CI2).getVectorizedFunction(Shape)) ||
             !CI->hasIdenticalOperandBundleSchema(*CI2)) {
           BS.cancelScheduling(VL, VL0);
           newTreeEntry(VL, None /*not vectorized*/, S, UserTreeIdx,
@@ -4507,7 +4514,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
       Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
 
       auto VecCallCosts = getVectorCallCosts(CI, VecTy, TTI, TLI);
-      bool UseIntrinsic = VecCallCosts.first <= VecCallCosts.second;
+      bool UseIntrinsic = ID != Intrinsic::not_intrinsic &&
+                          VecCallCosts.first <= VecCallCosts.second;
 
       Value *ScalarArg = nullptr;
       std::vector OpVecs;
@@ -4527,15 +4535,16 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
         OpVecs.push_back(OpVec);
       }
 
-      Module *M = F->getParent();
-      Type *Tys[] = {FixedVectorType::get(CI->getType(), E->Scalars.size())};
-      Function *CF = Intrinsic::getDeclaration(M, ID, Tys);
-
+      Function *CF;
       if (!UseIntrinsic) {
         VFShape Shape = VFShape::get(
             *CI, {static_cast(VecTy->getNumElements()), false},
             false /*HasGlobalPred*/);
         CF = VFDatabase(*CI).getVectorizedFunction(Shape);
+      } else {
+        Module *M = F->getParent();
+        Type *Tys[] = {FixedVectorType::get(CI->getType(), E->Scalars.size())};
+        CF = Intrinsic::getDeclaration(M, ID, Tys);
       }
 
       SmallVector OpBundles;
diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/accelerate-vector-functions.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/accelerate-vector-functions.ll
index 1cd93d20f85e8..811f414742f8e 100644
--- a/llvm/test/Transforms/SLPVectorizer/AArch64/accelerate-vector-functions.ll
+++ b/llvm/test/Transforms/SLPVectorizer/AArch64/accelerate-vector-functions.ll
@@ -344,18 +344,15 @@ define <4 x float> @expm1_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @expm1_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @expm1f(float [[VECEXT]]) #2
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @expm1f(float [[VECEXT_1]]) #2
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @expm1f(float [[VECEXT_2]]) #2
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @expm1f(float [[VECEXT_3]]) #2
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vexpm1f(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @expm1_4x(
@@ -445,18 +442,15 @@ define <4 x float> @log1p_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @log1p_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @log1pf(float [[VECEXT]]) #3
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @log1pf(float [[VECEXT_1]]) #3
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @log1pf(float [[VECEXT_2]]) #3
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @log1pf(float [[VECEXT_3]]) #3
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vlog1pf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @log1p_4x(
@@ -549,18 +543,15 @@ define <4 x float> @logb_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @logb_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @logbf(float [[VECEXT]]) #4
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @logbf(float [[VECEXT_1]]) #4
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @logbf(float [[VECEXT_2]]) #4
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @logbf(float [[VECEXT_3]]) #4
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vlogbf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @logb_4x(
@@ -699,18 +690,15 @@ define <4 x float> @tan_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @tan_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @tanf(float [[VECEXT]]) #5
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @tanf(float [[VECEXT_1]]) #5
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @tanf(float [[VECEXT_2]]) #5
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @tanf(float [[VECEXT_3]]) #5
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vtanf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @tan_4x(
@@ -751,18 +739,15 @@ define <4 x float> @asin_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @asin_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @asinf(float [[VECEXT]]) #6
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @asinf(float [[VECEXT_1]]) #6
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @asinf(float [[VECEXT_2]]) #6
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @asinf(float [[VECEXT_3]]) #6
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vasinf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @asin_4x(
@@ -803,18 +788,15 @@ define <4 x float> @acos_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @acos_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @acosf(float [[VECEXT]]) #7
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @acosf(float [[VECEXT_1]]) #7
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @acosf(float [[VECEXT_2]]) #7
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @acosf(float [[VECEXT_3]]) #7
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vacosf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @acos_4x(
@@ -855,18 +837,15 @@ define <4 x float> @atan_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @atan_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @atanf(float [[VECEXT]]) #8
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @atanf(float [[VECEXT_1]]) #8
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @atanf(float [[VECEXT_2]]) #8
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @atanf(float [[VECEXT_3]]) #8
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vatanf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @atan_4x(
@@ -907,18 +886,15 @@ define <4 x float> @sinh_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @sinh_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @sinhf(float [[VECEXT]]) #9
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @sinhf(float [[VECEXT_1]]) #9
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @sinhf(float [[VECEXT_2]]) #9
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @sinhf(float [[VECEXT_3]]) #9
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vsinhf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @sinh_4x(
@@ -959,18 +935,15 @@ define <4 x float> @cosh_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @cosh_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @coshf(float [[VECEXT]]) #10
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @coshf(float [[VECEXT_1]]) #10
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @coshf(float [[VECEXT_2]]) #10
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @coshf(float [[VECEXT_3]]) #10
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vcoshf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @cosh_4x(
@@ -1011,18 +984,15 @@ define <4 x float> @tanh_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @tanh_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @tanhf(float [[VECEXT]]) #11
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @tanhf(float [[VECEXT_1]]) #11
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @tanhf(float [[VECEXT_2]]) #11
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @tanhf(float [[VECEXT_3]]) #11
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vtanhf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @tanh_4x(
@@ -1063,18 +1033,15 @@ define <4 x float> @asinh_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @asinh_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @asinhf(float [[VECEXT]]) #12
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @asinhf(float [[VECEXT_1]]) #12
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @asinhf(float [[VECEXT_2]]) #12
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @asinhf(float [[VECEXT_3]]) #12
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vasinhf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @asinh_4x(
@@ -1115,18 +1082,15 @@ define <4 x float> @acosh_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @acosh_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @acoshf(float [[VECEXT]]) #13
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @acoshf(float [[VECEXT_1]]) #13
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @acoshf(float [[VECEXT_2]]) #13
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @acoshf(float [[VECEXT_3]]) #13
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vacoshf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @acosh_4x(
@@ -1167,18 +1131,15 @@ define <4 x float> @atanh_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @atanh_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @atanhf(float [[VECEXT]]) #14
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @atanhf(float [[VECEXT_1]]) #14
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @atanhf(float [[VECEXT_2]]) #14
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @atanhf(float [[VECEXT_3]]) #14
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vatanhf(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 ; NOACCELERATE-LABEL: @atanh_4x(
@@ -1221,10 +1182,10 @@ define <2 x float> @sin_2x(<2 x float>* %a) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x float>, <2 x float>* [[A:%.*]], align 16
 ; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <2 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT]]) #15
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT]]) #2
 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <2 x float> undef, float [[TMP1]], i32 0
 ; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <2 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_1]]) #15
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.sin.f32(float [[VECEXT_1]]) #2
 ; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <2 x float> [[VECINS]], float [[TMP2]], i32 1
 ; CHECK-NEXT:    ret <2 x float> [[VECINS_1]]
 ;
@@ -1309,10 +1270,10 @@ define <2 x float> @cos_2x(<2 x float>* %a) {
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <2 x float>, <2 x float>* [[A:%.*]], align 16
 ; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <2 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.cos.f32(float [[VECEXT]]) #16
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @llvm.cos.f32(float [[VECEXT]]) #3
 ; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <2 x float> undef, float [[TMP1]], i32 0
 ; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <2 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.cos.f32(float [[VECEXT_1]]) #16
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @llvm.cos.f32(float [[VECEXT_1]]) #3
 ; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <2 x float> [[VECINS]], float [[TMP2]], i32 1
 ; CHECK-NEXT:    ret <2 x float> [[VECINS_1]]
 ;
diff --git a/llvm/test/Transforms/SLPVectorizer/vectorizable-functions.ll b/llvm/test/Transforms/SLPVectorizer/vectorizable-functions.ll
index bb27efbf424ec..ca724d46bea82 100644
--- a/llvm/test/Transforms/SLPVectorizer/vectorizable-functions.ll
+++ b/llvm/test/Transforms/SLPVectorizer/vectorizable-functions.ll
@@ -8,18 +8,15 @@ define <4 x float> @memread_4x(<4 x float>* %a) {
 ; CHECK-LABEL: @memread_4x(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, <4 x float>* [[A:%.*]], align 16
-; CHECK-NEXT:    [[VECEXT:%.*]] = extractelement <4 x float> [[TMP0]], i32 0
-; CHECK-NEXT:    [[TMP1:%.*]] = tail call fast float @memread(float [[VECEXT]]) #2
-; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP1]], i32 0
-; CHECK-NEXT:    [[VECEXT_1:%.*]] = extractelement <4 x float> [[TMP0]], i32 1
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call fast float @memread(float [[VECEXT_1]]) #2
-; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP2]], i32 1
-; CHECK-NEXT:    [[VECEXT_2:%.*]] = extractelement <4 x float> [[TMP0]], i32 2
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call fast float @memread(float [[VECEXT_2]]) #2
-; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP3]], i32 2
-; CHECK-NEXT:    [[VECEXT_3:%.*]] = extractelement <4 x float> [[TMP0]], i32 3
-; CHECK-NEXT:    [[TMP4:%.*]] = tail call fast float @memread(float [[VECEXT_3]]) #2
-; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP4]], i32 3
+; CHECK-NEXT:    [[TMP1:%.*]] = call fast <4 x float> @vmemread(<4 x float> [[TMP0]])
+; CHECK-NEXT:    [[TMP2:%.*]] = extractelement <4 x float> [[TMP1]], i32 0
+; CHECK-NEXT:    [[VECINS:%.*]] = insertelement <4 x float> undef, float [[TMP2]], i32 0
+; CHECK-NEXT:    [[TMP3:%.*]] = extractelement <4 x float> [[TMP1]], i32 1
+; CHECK-NEXT:    [[VECINS_1:%.*]] = insertelement <4 x float> [[VECINS]], float [[TMP3]], i32 1
+; CHECK-NEXT:    [[TMP4:%.*]] = extractelement <4 x float> [[TMP1]], i32 2
+; CHECK-NEXT:    [[VECINS_2:%.*]] = insertelement <4 x float> [[VECINS_1]], float [[TMP4]], i32 2
+; CHECK-NEXT:    [[TMP5:%.*]] = extractelement <4 x float> [[TMP1]], i32 3
+; CHECK-NEXT:    [[VECINS_3:%.*]] = insertelement <4 x float> [[VECINS_2]], float [[TMP5]], i32 3
 ; CHECK-NEXT:    ret <4 x float> [[VECINS_3]]
 ;
 entry:

From 13fec93a77fa159d700eff40b27402520eed2dfa Mon Sep 17 00:00:00 2001
From: Sanne Wouda 
Date: Fri, 3 Jul 2020 12:37:21 +0100
Subject: [PATCH 101/771] [NFC] rename to reflect F is not necessarily an
 Intrinsic

---
 llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index fe9ea2995377c..5bc35aa4695f8 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -3039,7 +3039,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth,
         LLVM_DEBUG(dbgs() << "SLP: Non-vectorizable call.\n");
         return;
       }
-      Function *Int = CI->getCalledFunction();
+      Function *F = CI->getCalledFunction();
       unsigned NumArgs = CI->getNumArgOperands();
       SmallVector ScalarArgs(NumArgs, nullptr);
       for (unsigned j = 0; j != NumArgs; ++j)
@@ -3047,7 +3047,7 @@ void BoUpSLP::buildTree_rec(ArrayRef VL, unsigned Depth,
           ScalarArgs[j] = CI->getArgOperand(j);
       for (Value *V : VL) {
         CallInst *CI2 = dyn_cast(V);
-        if (!CI2 || CI2->getCalledFunction() != Int ||
+        if (!CI2 || CI2->getCalledFunction() != F ||
             getVectorIntrinsicIDForCall(CI2, TLI) != ID ||
             (VecFunc &&
              VecFunc != VFDatabase(*CI2).getVectorizedFunction(Shape)) ||
@@ -4542,9 +4542,8 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
             false /*HasGlobalPred*/);
         CF = VFDatabase(*CI).getVectorizedFunction(Shape);
       } else {
-        Module *M = F->getParent();
         Type *Tys[] = {FixedVectorType::get(CI->getType(), E->Scalars.size())};
-        CF = Intrinsic::getDeclaration(M, ID, Tys);
+        CF = Intrinsic::getDeclaration(F->getParent(), ID, Tys);
       }
 
       SmallVector OpBundles;

From a5803765d8e0b62e0b48ea76bcad07a7c183618b Mon Sep 17 00:00:00 2001
From: Pavel Labath 
Date: Fri, 10 Jul 2020 13:18:00 +0200
Subject: [PATCH 102/771] [lldb/dotest] Remove the "xunit" result formatter

Summary:
My understanding is that this was added to make dotest interact well
with the GreenDragon bots, back when dotest was the main test driver.
Now that everything goes through lit (which has its own xunit
formatter), it seems largely irrelevant.

There are more cleanups that can be done after removing this be done
here, but this should be enough to test the waters.

Reviewers: JDevlieghere

Subscribers: lldb-commits

Tags: #lldb

Differential Revision: https://reviews.llvm.org/D83545
---
 .../Python/lldbsuite/test/configuration.py    |   4 -
 lldb/packages/Python/lldbsuite/test/dotest.py |  21 +-
 .../Python/lldbsuite/test/dotest_args.py      |  22 -
 .../test_event/formatter/__init__.py          | 113 +---
 .../lldbsuite/test_event/formatter/xunit.py   | 595 ------------------
 5 files changed, 30 insertions(+), 725 deletions(-)
 delete mode 100644 lldb/packages/Python/lldbsuite/test_event/formatter/xunit.py

diff --git a/lldb/packages/Python/lldbsuite/test/configuration.py b/lldb/packages/Python/lldbsuite/test/configuration.py
index ca27864463002..84de0130f9907 100644
--- a/lldb/packages/Python/lldbsuite/test/configuration.py
+++ b/lldb/packages/Python/lldbsuite/test/configuration.py
@@ -122,10 +122,6 @@
 clang_module_cache_dir = None
 
 # Test results handling globals
-results_filename = None
-results_formatter_name = None
-results_formatter_object = None
-results_formatter_options = None
 test_result = None
 
 # Reproducers
diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py
index 8238168d0fb6d..67f227cad7155 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest.py
@@ -408,19 +408,6 @@ def parseOptionsAndInitTestdirs():
     if do_help:
         usage(parser)
 
-    if args.results_file:
-        configuration.results_filename = args.results_file
-
-    if args.results_formatter:
-        configuration.results_formatter_name = args.results_formatter
-    if args.results_formatter_options:
-        configuration.results_formatter_options = args.results_formatter_options
-
-    # Default to using the BasicResultsFormatter if no formatter is specified.
-    if configuration.results_formatter_name is None:
-        configuration.results_formatter_name = (
-            "lldbsuite.test_event.formatter.results_formatter.ResultsFormatter")
-
     # Reproducer arguments
     if args.capture_path and args.replay_path:
         logging.error('Cannot specify both a capture and a replay path.')
@@ -469,16 +456,10 @@ def parseOptionsAndInitTestdirs():
 
 def setupTestResults():
     """Sets up test results-related objects based on arg settings."""
-    # Setup the results formatter configuration.
-    formatter_config = formatter.FormatterConfig()
-    formatter_config.filename = configuration.results_filename
-    formatter_config.formatter_name = configuration.results_formatter_name
-    formatter_config.formatter_options = (
-        configuration.results_formatter_options)
 
     # Create the results formatter.
     formatter_spec = formatter.create_results_formatter(
-        formatter_config)
+            "lldbsuite.test_event.formatter.results_formatter.ResultsFormatter")
     if formatter_spec is not None and formatter_spec.formatter is not None:
         configuration.results_formatter_object = formatter_spec.formatter
 
diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py
index d6f59efdf28b4..05dd523e744ac 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest_args.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py
@@ -244,28 +244,6 @@ def create_parser():
         help='(Windows only) When LLDB crashes, display the Windows crash dialog.')
     group.set_defaults(disable_crash_dialog=True)
 
-    # Test results support.
-    group = parser.add_argument_group('Test results options')
-    group.add_argument(
-        '--results-file',
-        action='store',
-        help=('Specifies the file where test results will be written '
-              'according to the results-formatter class used'))
-    group.add_argument(
-        '--results-formatter',
-        action='store',
-        help=('Specifies the full package/module/class name used to translate '
-              'test events into some kind of meaningful report, written to '
-              'the designated output results file-like object'))
-    group.add_argument(
-        '--results-formatter-option',
-        '-O',
-        action='append',
-        dest='results_formatter_options',
-        help=('Specify an option to pass to the formatter. '
-              'Use --results-formatter-option="--option1=val1" '
-              'syntax.  Note the "=" is critical, don\'t include whitespace.'))
-
     # Re-run related arguments
     group = parser.add_argument_group('Test Re-run Options')
     group.add_argument(
diff --git a/lldb/packages/Python/lldbsuite/test_event/formatter/__init__.py b/lldb/packages/Python/lldbsuite/test_event/formatter/__init__.py
index 1fe6ecd3ef82f..d6609d353c856 100644
--- a/lldb/packages/Python/lldbsuite/test_event/formatter/__init__.py
+++ b/lldb/packages/Python/lldbsuite/test_event/formatter/__init__.py
@@ -17,17 +17,6 @@
 # LLDB modules
 
 
-# Ignore method count on DTOs.
-# pylint: disable=too-few-public-methods
-class FormatterConfig(object):
-    """Provides formatter configuration info to create_results_formatter()."""
-
-    def __init__(self):
-        self.filename = None
-        self.formatter_name = None
-        self.formatter_options = None
-
-
 # Ignore method count on DTOs.
 # pylint: disable=too-few-public-methods
 class CreatedFormatter(object):
@@ -38,7 +27,7 @@ def __init__(self, formatter, cleanup_func):
         self.cleanup_func = cleanup_func
 
 
-def create_results_formatter(config):
+def create_results_formatter(formatter_name):
     """Sets up a test results formatter.
 
     @param config an instance of FormatterConfig
@@ -47,75 +36,31 @@ def create_results_formatter(config):
     @return an instance of CreatedFormatter.
     """
 
-    default_formatter_name = None
-    results_file_object = None
-    cleanup_func = None
-
-    if config.filename:
-        # Open the results file for writing.
-        if config.filename == 'stdout':
-            results_file_object = sys.stdout
-            cleanup_func = None
-        elif config.filename == 'stderr':
-            results_file_object = sys.stderr
-            cleanup_func = None
-        else:
-            results_file_object = open(config.filename, "w")
-            cleanup_func = results_file_object.close
-        default_formatter_name = (
-            "lldbsuite.test_event.formatter.xunit.XunitFormatter")
-
-    # If we have a results formatter name specified and we didn't specify
-    # a results file, we should use stdout.
-    if config.formatter_name is not None and results_file_object is None:
-        # Use stdout.
-        results_file_object = sys.stdout
-        cleanup_func = None
-
-    if results_file_object:
-        # We care about the formatter.  Choose user-specified or, if
-        # none specified, use the default for the output type.
-        if config.formatter_name:
-            formatter_name = config.formatter_name
-        else:
-            formatter_name = default_formatter_name
-
-        # Create an instance of the class.
-        # First figure out the package/module.
-        components = formatter_name.split(".")
-        module = importlib.import_module(".".join(components[:-1]))
-
-        # Create the class name we need to load.
-        cls = getattr(module, components[-1])
-
-        # Handle formatter options for the results formatter class.
-        formatter_arg_parser = cls.arg_parser()
-        if config.formatter_options and len(config.formatter_options) > 0:
-            command_line_options = config.formatter_options
-        else:
-            command_line_options = []
-
-        formatter_options = formatter_arg_parser.parse_args(
-            command_line_options)
-
-        # Create the TestResultsFormatter given the processed options.
-        results_formatter_object = cls(
-            results_file_object,
-            formatter_options)
-
-        def shutdown_formatter():
-            """Shuts down the formatter when it is no longer needed."""
-            # Tell the formatter to write out anything it may have
-            # been saving until the very end (e.g. xUnit results
-            # can't complete its output until this point).
-            results_formatter_object.send_terminate_as_needed()
-
-            # And now close out the output file-like object.
-            if cleanup_func is not None:
-                cleanup_func()
-
-        return CreatedFormatter(
-            results_formatter_object,
-            shutdown_formatter)
-    else:
-        return None
+    # Create an instance of the class.
+    # First figure out the package/module.
+    components = formatter_name.split(".")
+    module = importlib.import_module(".".join(components[:-1]))
+
+    # Create the class name we need to load.
+    cls = getattr(module, components[-1])
+
+    # Handle formatter options for the results formatter class.
+    formatter_arg_parser = cls.arg_parser()
+    command_line_options = []
+
+    formatter_options = formatter_arg_parser.parse_args(
+        command_line_options)
+
+    # Create the TestResultsFormatter given the processed options.
+    results_formatter_object = cls(sys.stdout, formatter_options)
+
+    def shutdown_formatter():
+        """Shuts down the formatter when it is no longer needed."""
+        # Tell the formatter to write out anything it may have
+        # been saving until the very end (e.g. xUnit results
+        # can't complete its output until this point).
+        results_formatter_object.send_terminate_as_needed()
+
+    return CreatedFormatter(
+        results_formatter_object,
+        shutdown_formatter)
diff --git a/lldb/packages/Python/lldbsuite/test_event/formatter/xunit.py b/lldb/packages/Python/lldbsuite/test_event/formatter/xunit.py
deleted file mode 100644
index e480df59a2f28..0000000000000
--- a/lldb/packages/Python/lldbsuite/test_event/formatter/xunit.py
+++ /dev/null
@@ -1,595 +0,0 @@
-"""
-Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-See https://llvm.org/LICENSE.txt for license information.
-SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-Provides an xUnit ResultsFormatter for integrating the LLDB
-test suite with the Jenkins xUnit aggregator and other xUnit-compliant
-test output processors.
-"""
-from __future__ import absolute_import
-from __future__ import print_function
-
-# System modules
-import re
-import sys
-import xml.sax.saxutils
-
-# Third-party modules
-import six
-
-# Local modules
-from ..event_builder import EventBuilder
-from ..build_exception import BuildError
-from .results_formatter import ResultsFormatter
-
-
-class XunitFormatter(ResultsFormatter):
-    """Provides xUnit-style formatted output.
-    """
-
-    # Result mapping arguments
-    RM_IGNORE = 'ignore'
-    RM_SUCCESS = 'success'
-    RM_FAILURE = 'failure'
-    RM_PASSTHRU = 'passthru'
-
-    @staticmethod
-    def _build_illegal_xml_regex():
-        """Constructs a regex to match all illegal xml characters.
-
-        Expects to be used against a unicode string."""
-        # Construct the range pairs of invalid unicode characters.
-        illegal_chars_u = [
-            (0x00, 0x08), (0x0B, 0x0C), (0x0E, 0x1F), (0x7F, 0x84),
-            (0x86, 0x9F), (0xFDD0, 0xFDDF), (0xFFFE, 0xFFFF)]
-
-        # For wide builds, we have more.
-        if sys.maxunicode >= 0x10000:
-            illegal_chars_u.extend(
-                [(0x1FFFE, 0x1FFFF), (0x2FFFE, 0x2FFFF), (0x3FFFE, 0x3FFFF),
-                 (0x4FFFE, 0x4FFFF), (0x5FFFE, 0x5FFFF), (0x6FFFE, 0x6FFFF),
-                 (0x7FFFE, 0x7FFFF), (0x8FFFE, 0x8FFFF), (0x9FFFE, 0x9FFFF),
-                 (0xAFFFE, 0xAFFFF), (0xBFFFE, 0xBFFFF), (0xCFFFE, 0xCFFFF),
-                 (0xDFFFE, 0xDFFFF), (0xEFFFE, 0xEFFFF), (0xFFFFE, 0xFFFFF),
-                 (0x10FFFE, 0x10FFFF)])
-
-        # Build up an array of range expressions.
-        illegal_ranges = [
-            "%s-%s" % (six.unichr(low), six.unichr(high))
-            for (low, high) in illegal_chars_u]
-
-        # Compile the regex
-        return re.compile(six.u('[%s]') % six.u('').join(illegal_ranges))
-
-    @staticmethod
-    def _quote_attribute(text):
-        """Returns the given text in a manner safe for usage in an XML attribute.
-
-        @param text the text that should appear within an XML attribute.
-        @return the attribute-escaped version of the input text.
-        """
-        return xml.sax.saxutils.quoteattr(text)
-
-    def _replace_invalid_xml(self, str_or_unicode):
-        """Replaces invalid XML characters with a '?'.
-
-        @param str_or_unicode a string to replace invalid XML
-        characters within.  Can be unicode or not.  If not unicode,
-        assumes it is a byte string in utf-8 encoding.
-
-        @returns a utf-8-encoded byte string with invalid
-        XML replaced with '?'.
-        """
-        # Get the content into unicode
-        if isinstance(str_or_unicode, str):
-            # If we hit decoding errors due to data corruption, replace the
-            # invalid characters with U+FFFD REPLACEMENT CHARACTER.
-            unicode_content = str_or_unicode.decode('utf-8', 'replace')
-        else:
-            unicode_content = str_or_unicode
-        return self.invalid_xml_re.sub(
-            six.u('?'), unicode_content).encode('utf-8')
-
-    @classmethod
-    def arg_parser(cls):
-        """@return arg parser used to parse formatter-specific options."""
-        parser = super(XunitFormatter, cls).arg_parser()
-
-        # These are valid choices for results mapping.
-        results_mapping_choices = [
-            XunitFormatter.RM_IGNORE,
-            XunitFormatter.RM_SUCCESS,
-            XunitFormatter.RM_FAILURE,
-            XunitFormatter.RM_PASSTHRU]
-        parser.add_argument(
-            "--assert-on-unknown-events",
-            action="store_true",
-            help=('cause unknown test events to generate '
-                  'a python assert.  Default is to ignore.'))
-        parser.add_argument(
-            "--ignore-skip-name",
-            "-n",
-            metavar='PATTERN',
-            action="append",
-            dest='ignore_skip_name_patterns',
-            help=('a python regex pattern, where '
-                  'any skipped test with a test method name where regex '
-                  'matches (via search) will be ignored for xUnit test '
-                  'result purposes.  Can be specified multiple times.'))
-        parser.add_argument(
-            "--ignore-skip-reason",
-            "-r",
-            metavar='PATTERN',
-            action="append",
-            dest='ignore_skip_reason_patterns',
-            help=('a python regex pattern, where '
-                  'any skipped test with a skip reason where the regex '
-                  'matches (via search) will be ignored for xUnit test '
-                  'result purposes.  Can be specified multiple times.'))
-        parser.add_argument(
-            "--xpass", action="store", choices=results_mapping_choices,
-            default=XunitFormatter.RM_FAILURE,
-            help=('specify mapping from unexpected success to jUnit/xUnit '
-                  'result type'))
-        parser.add_argument(
-            "--xfail", action="store", choices=results_mapping_choices,
-            default=XunitFormatter.RM_IGNORE,
-            help=('specify mapping from expected failure to jUnit/xUnit '
-                  'result type'))
-        return parser
-
-    @staticmethod
-    def _build_regex_list_from_patterns(patterns):
-        """Builds a list of compiled regular expressions from option value.
-
-        @param patterns contains a list of regular expression
-        patterns.
-
-        @return list of compiled regular expressions, empty if no
-        patterns provided.
-        """
-        regex_list = []
-        if patterns is not None:
-            for pattern in patterns:
-                regex_list.append(re.compile(pattern))
-        return regex_list
-
-    def __init__(self, out_file, options):
-        """Initializes the XunitFormatter instance.
-        @param out_file file-like object where formatted output is written.
-        @param options specifies a dictionary of options for the
-        formatter.
-        """
-        # Initialize the parent
-        super(XunitFormatter, self).__init__(out_file, options)
-        self.text_encoding = "UTF-8"
-        self.invalid_xml_re = XunitFormatter._build_illegal_xml_regex()
-        self.total_test_count = 0
-        self.ignore_skip_name_regexes = (
-            XunitFormatter._build_regex_list_from_patterns(
-                options.ignore_skip_name_patterns))
-        self.ignore_skip_reason_regexes = (
-            XunitFormatter._build_regex_list_from_patterns(
-                options.ignore_skip_reason_patterns))
-
-        self.elements = {
-            "successes": [],
-            "errors": [],
-            "failures": [],
-            "skips": [],
-            "unexpected_successes": [],
-            "expected_failures": [],
-            "all": []
-        }
-
-        self.status_handlers = {
-            EventBuilder.STATUS_SUCCESS: self._handle_success,
-            EventBuilder.STATUS_FAILURE: self._handle_failure,
-            EventBuilder.STATUS_ERROR: self._handle_error,
-            EventBuilder.STATUS_SKIP: self._handle_skip,
-            EventBuilder.STATUS_EXPECTED_FAILURE:
-                self._handle_expected_failure,
-            EventBuilder.STATUS_EXPECTED_TIMEOUT:
-                self._handle_expected_timeout,
-            EventBuilder.STATUS_UNEXPECTED_SUCCESS:
-                self._handle_unexpected_success,
-            EventBuilder.STATUS_EXCEPTIONAL_EXIT:
-                self._handle_exceptional_exit,
-            EventBuilder.STATUS_TIMEOUT:
-                self._handle_timeout
-        }
-
-    RESULT_TYPES = {
-        EventBuilder.TYPE_TEST_RESULT,
-        EventBuilder.TYPE_JOB_RESULT}
-
-    def handle_event(self, test_event):
-        super(XunitFormatter, self).handle_event(test_event)
-
-        event_type = test_event["event"]
-        if event_type is None:
-            return
-
-        if event_type == "terminate":
-            # Process all the final result events into their
-            # XML counterparts.
-            for result_event in self.result_events.values():
-                self._process_test_result(result_event)
-            self._finish_output()
-        else:
-            # This is an unknown event.
-            if self.options.assert_on_unknown_events:
-                raise Exception("unknown event type {} from {}\n".format(
-                    event_type, test_event))
-
-    def _handle_success(self, test_event):
-        """Handles a test success.
-        @param test_event the test event to handle.
-        """
-        result = self._common_add_testcase_entry(test_event)
-        with self.lock:
-            self.elements["successes"].append(result)
-
-    def _handle_failure(self, test_event):
-        """Handles a test failure.
-        @param test_event the test event to handle.
-        """
-        message = self._replace_invalid_xml(test_event["issue_message"])
-        backtrace = self._replace_invalid_xml(
-            "".join(test_event.get("issue_backtrace", [])))
-
-        result = self._common_add_testcase_entry(
-            test_event,
-            inner_content=(
-                ''.format(
-                    XunitFormatter._quote_attribute(test_event["issue_class"]),
-                    XunitFormatter._quote_attribute(message),
-                    backtrace)
-            ))
-        with self.lock:
-            self.elements["failures"].append(result)
-
-    def _handle_error_build(self, test_event):
-        """Handles a test error.
-        @param test_event the test event to handle.
-        """
-        message = self._replace_invalid_xml(test_event["issue_message"])
-        build_issue_description = self._replace_invalid_xml(
-            BuildError.format_build_error(
-                test_event.get("build_command", ""),
-                test_event.get("build_error", "")))
-
-        result = self._common_add_testcase_entry(
-            test_event,
-            inner_content=(
-                ''.format(
-                    XunitFormatter._quote_attribute(test_event["issue_class"]),
-                    XunitFormatter._quote_attribute(message),
-                    build_issue_description)
-            ))
-        with self.lock:
-            self.elements["errors"].append(result)
-
-    def _handle_error_standard(self, test_event):
-        """Handles a test error.
-        @param test_event the test event to handle.
-        """
-        message = self._replace_invalid_xml(test_event["issue_message"])
-        backtrace = self._replace_invalid_xml(
-            "".join(test_event.get("issue_backtrace", [])))
-
-        result = self._common_add_testcase_entry(
-            test_event,
-            inner_content=(
-                ''.format(
-                    XunitFormatter._quote_attribute(test_event["issue_class"]),
-                    XunitFormatter._quote_attribute(message),
-                    backtrace)
-            ))
-        with self.lock:
-            self.elements["errors"].append(result)
-
-    def _handle_error(self, test_event):
-        if test_event.get("issue_phase", None) == "build":
-            self._handle_error_build(test_event)
-        else:
-            self._handle_error_standard(test_event)
-
-    def _handle_exceptional_exit(self, test_event):
-        """Handles an exceptional exit.
-        @param test_event the test method or job result event to handle.
-        """
-        if "test_name" in test_event:
-            name = test_event["test_name"]
-        else:
-            name = test_event.get("test_filename", "")
-
-        message_text = "ERROR: {} ({}): {}".format(
-            test_event.get("exception_code", 0),
-            test_event.get("exception_description", ""),
-            name)
-        message = self._replace_invalid_xml(message_text)
-
-        result = self._common_add_testcase_entry(
-            test_event,
-            inner_content=(
-                ''.format(
-                    "exceptional_exit",
-                    XunitFormatter._quote_attribute(message))
-            ))
-        with self.lock:
-            self.elements["errors"].append(result)
-
-    def _handle_timeout(self, test_event):
-        """Handles a test method or job timeout.
-        @param test_event the test method or job result event to handle.
-        """
-        if "test_name" in test_event:
-            name = test_event["test_name"]
-        else:
-            name = test_event.get("test_filename", "")
-
-        message_text = "TIMEOUT: {}".format(name)
-        message = self._replace_invalid_xml(message_text)
-
-        result = self._common_add_testcase_entry(
-            test_event,
-            inner_content=(
-                ''.format(
-                    XunitFormatter._quote_attribute("timeout"),
-                    XunitFormatter._quote_attribute(message))
-            ))
-        with self.lock:
-            self.elements["errors"].append(result)
-
-    @staticmethod
-    def _ignore_based_on_regex_list(test_event, test_key, regex_list):
-        """Returns whether to ignore a test event based on patterns.
-
-        @param test_event the test event dictionary to check.
-        @param test_key the key within the dictionary to check.
-        @param regex_list a list of zero or more regexes.  May contain
-        zero or more compiled regexes.
-
-        @return True if any o the regex list match based on the
-        re.search() method; false otherwise.
-        """
-        for regex in regex_list:
-            match = regex.search(test_event.get(test_key, ''))
-            if match:
-                return True
-        return False
-
-    def _handle_skip(self, test_event):
-        """Handles a skipped test.
-        @param test_event the test event to handle.
-        """
-
-        # Are we ignoring this test based on test name?
-        if XunitFormatter._ignore_based_on_regex_list(
-                test_event, 'test_name', self.ignore_skip_name_regexes):
-            return
-
-        # Are we ignoring this test based on skip reason?
-        if XunitFormatter._ignore_based_on_regex_list(
-                test_event, 'skip_reason', self.ignore_skip_reason_regexes):
-            return
-
-        # We're not ignoring this test.  Process the skip.
-        reason = self._replace_invalid_xml(test_event.get("skip_reason", ""))
-        result = self._common_add_testcase_entry(
-            test_event,
-            inner_content=''.format(
-                XunitFormatter._quote_attribute(reason)))
-        with self.lock:
-            self.elements["skips"].append(result)
-
-    def _handle_expected_failure(self, test_event):
-        """Handles a test that failed as expected.
-        @param test_event the test event to handle.
-        """
-        if self.options.xfail == XunitFormatter.RM_PASSTHRU:
-            # This is not a natively-supported junit/xunit
-            # testcase mode, so it might fail a validating
-            # test results viewer.
-            if "bugnumber" in test_event:
-                bug_id_attribute = 'bug-id={} '.format(
-                    XunitFormatter._quote_attribute(test_event["bugnumber"]))
-            else:
-                bug_id_attribute = ''
-
-            result = self._common_add_testcase_entry(
-                test_event,
-                inner_content=(
-                    ''.format(
-                        bug_id_attribute,
-                        XunitFormatter._quote_attribute(
-                            test_event["issue_class"]),
-                        XunitFormatter._quote_attribute(
-                            test_event["issue_message"]))
-                ))
-            with self.lock:
-                self.elements["expected_failures"].append(result)
-        elif self.options.xfail == XunitFormatter.RM_SUCCESS:
-            result = self._common_add_testcase_entry(test_event)
-            with self.lock:
-                self.elements["successes"].append(result)
-        elif self.options.xfail == XunitFormatter.RM_FAILURE:
-            result = self._common_add_testcase_entry(
-                test_event,
-                inner_content=''.format(
-                    XunitFormatter._quote_attribute(test_event["issue_class"]),
-                    XunitFormatter._quote_attribute(
-                        test_event["issue_message"])))
-            with self.lock:
-                self.elements["failures"].append(result)
-        elif self.options.xfail == XunitFormatter.RM_IGNORE:
-            pass
-        else:
-            raise Exception(
-                "unknown xfail option: {}".format(self.options.xfail))
-
-    @staticmethod
-    def _handle_expected_timeout(test_event):
-        """Handles expected_timeout.
-        @param test_event the test event to handle.
-        """
-        # We don't do anything with expected timeouts, not even report.
-        pass
-
-    def _handle_unexpected_success(self, test_event):
-        """Handles a test that passed but was expected to fail.
-        @param test_event the test event to handle.
-        """
-        if self.options.xpass == XunitFormatter.RM_PASSTHRU:
-            # This is not a natively-supported junit/xunit
-            # testcase mode, so it might fail a validating
-            # test results viewer.
-            result = self._common_add_testcase_entry(
-                test_event,
-                inner_content="")
-            with self.lock:
-                self.elements["unexpected_successes"].append(result)
-        elif self.options.xpass == XunitFormatter.RM_SUCCESS:
-            # Treat the xpass as a success.
-            result = self._common_add_testcase_entry(test_event)
-            with self.lock:
-                self.elements["successes"].append(result)
-        elif self.options.xpass == XunitFormatter.RM_FAILURE:
-            # Treat the xpass as a failure.
-            if "bugnumber" in test_event:
-                message = "unexpected success (bug_id:{})".format(
-                    test_event["bugnumber"])
-            else:
-                message = "unexpected success (bug_id:none)"
-            result = self._common_add_testcase_entry(
-                test_event,
-                inner_content=''.format(
-                    XunitFormatter._quote_attribute("unexpected_success"),
-                    XunitFormatter._quote_attribute(message)))
-            with self.lock:
-                self.elements["failures"].append(result)
-        elif self.options.xpass == XunitFormatter.RM_IGNORE:
-            # Ignore the xpass result as far as xUnit reporting goes.
-            pass
-        else:
-            raise Exception("unknown xpass option: {}".format(
-                self.options.xpass))
-
-    def _process_test_result(self, test_event):
-        """Processes the test_event known to be a test result.
-
-        This categorizes the event appropriately and stores the data needed
-        to generate the final xUnit report.  This method skips events that
-        cannot be represented in xUnit output.
-        """
-        if "status" not in test_event:
-            raise Exception("test event dictionary missing 'status' key")
-
-        status = test_event["status"]
-        if status not in self.status_handlers:
-            raise Exception("test event status '{}' unsupported".format(
-                status))
-
-        # Call the status handler for the test result.
-        self.status_handlers[status](test_event)
-
-    def _common_add_testcase_entry(self, test_event, inner_content=None):
-        """Registers a testcase result, and returns the text created.
-
-        The caller is expected to manage failure/skip/success counts
-        in some kind of appropriate way.  This call simply constructs
-        the XML and appends the returned result to the self.all_results
-        list.
-
-        @param test_event the test event dictionary.
-
-        @param inner_content if specified, gets included in the 
-        inner section, at the point before stdout and stderr would be
-        included.  This is where a , , , etc.
-        could go.
-
-        @return the text of the xml testcase element.
-        """
-
-        # Get elapsed time.
-        test_class = test_event.get("test_class", "")
-        test_name = test_event.get("test_name", "")
-        event_time = test_event["event_time"]
-        time_taken = self.elapsed_time_for_test(
-            test_class, test_name, event_time)
-
-        # Plumb in stdout/stderr once we shift over to only test results.
-        test_stdout = ''
-        test_stderr = ''
-
-        # Formulate the output xml.
-        if not inner_content:
-            inner_content = ""
-        result = (
-            ''
-            '{}{}{}'.format(
-                test_class,
-                test_name,
-                time_taken,
-                inner_content,
-                test_stdout,
-                test_stderr))
-
-        # Save the result, update total test count.
-        with self.lock:
-            self.total_test_count += 1
-            self.elements["all"].append(result)
-
-        return result
-
-    def _finish_output_no_lock(self):
-        """Flushes out the report of test executions to form valid xml output.
-
-        xUnit output is in XML.  The reporting system cannot complete the
-        formatting of the output without knowing when there is no more input.
-        This call addresses notification of the completed test run and thus is
-        when we can finish off the report output.
-        """
-
-        # Figure out the counts line for the testsuite.  If we have
-        # been counting either unexpected successes or expected
-        # failures, we'll output those in the counts, at the risk of
-        # being invalidated by a validating test results viewer.
-        # These aren't counted by default so they won't show up unless
-        # the user specified a formatter option to include them.
-        xfail_count = len(self.elements["expected_failures"])
-        xpass_count = len(self.elements["unexpected_successes"])
-        if xfail_count > 0 or xpass_count > 0:
-            extra_testsuite_attributes = (
-                ' expected-failures="{}"'
-                ' unexpected-successes="{}"'.format(xfail_count, xpass_count))
-        else:
-            extra_testsuite_attributes = ""
-
-        # Output the header.
-        self.out_file.write(
-            '\n'
-            ''
-            '\n'.format(
-                self.text_encoding,
-                "LLDB test suite",
-                self.total_test_count,
-                len(self.elements["errors"]),
-                len(self.elements["failures"]),
-                len(self.elements["skips"]),
-                extra_testsuite_attributes))
-
-        # Output each of the test result entries.
-        for result in self.elements["all"]:
-            self.out_file.write(result + '\n')
-
-        # Close off the test suite.
-        self.out_file.write('\n')
-
-    def _finish_output(self):
-        """Finish writing output as all incoming events have arrived."""
-        with self.lock:
-            self._finish_output_no_lock()

From 4cdea5faf980951bf3c4cb4ade9850d27c32af16 Mon Sep 17 00:00:00 2001
From: Eric Astor 
Date: Mon, 13 Jul 2020 10:33:15 -0400
Subject: [PATCH 103/771] [ms] [llvm-ml] Improve MASM STRUCT field accessor
 support

Summary:
Adds support for several accessors:
- `[.].`
- `[..].` (where `field` has already-defined STRUCT type)
- `[.].` (where `field` has already-defined STRUCT type)

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D83344
---
 llvm/include/llvm/MC/MCParser/MCAsmParser.h   |  8 ++-
 llvm/lib/MC/MCParser/MasmParser.cpp           | 55 ++++++++++++++-----
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 33 ++++++-----
 llvm/test/tools/llvm-ml/struct.test           | 50 ++++++++++++++++-
 4 files changed, 113 insertions(+), 33 deletions(-)

diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
index 2040089759594..a68066e0f50b5 100644
--- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
@@ -170,8 +170,12 @@ class MCAsmParser {
 
   virtual bool isParsingMasm() const { return false; }
 
-  virtual bool LookUpFieldOffset(StringRef Base, StringRef Member,
-                                 unsigned &Offset) {
+  virtual bool lookUpField(StringRef Name, StringRef &Type,
+                           unsigned &Offset) const {
+    return true;
+  }
+  virtual bool lookUpField(StringRef Base, StringRef Member, StringRef &Type,
+                           unsigned &Offset) const {
     return true;
   }
 
diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index 3dbd00aae47a2..d7d0508cabff7 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -490,8 +490,10 @@ class MasmParser : public MCAsmParser {
 
   bool isParsingMasm() const override { return true; }
 
-  bool LookUpFieldOffset(StringRef Base, StringRef Member,
-                         unsigned &Offset) override;
+  bool lookUpField(StringRef Name, StringRef &Type,
+                   unsigned &Offset) const override;
+  bool lookUpField(StringRef Base, StringRef Member, StringRef &Type,
+                   unsigned &Offset) const override;
 
   bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
                         unsigned &NumOutputs, unsigned &NumInputs,
@@ -561,8 +563,8 @@ class MasmParser : public MCAsmParser {
   }
   static void DiagHandler(const SMDiagnostic &Diag, void *Context);
 
-  bool LookUpFieldOffset(const StructInfo &Structure, StringRef Member,
-                         unsigned &Offset);
+  bool lookUpField(const StructInfo &Structure, StringRef Member,
+                   StringRef &Type, unsigned &Offset) const;
 
   /// Should we emit DWARF describing this assembler source?  (Returns false if
   /// the source has .file directives, which means we don't want to generate
@@ -1397,12 +1399,13 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
     }
 
     // Find the field offset if used.
+    StringRef Type;
     unsigned Offset = 0;
     Split = SymbolName.split('.');
     if (!Split.second.empty()) {
       SymbolName = Split.first;
       if (Structs.count(SymbolName.lower()) &&
-          !LookUpFieldOffset(SymbolName, Split.second, Offset)) {
+          !lookUpField(SymbolName, Split.second, Type, Offset)) {
         // This is actually a reference to a field offset.
         Res = MCConstantExpr::create(Offset, getContext());
         return false;
@@ -1410,10 +1413,10 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
 
       auto TypeIt = KnownType.find(SymbolName);
       if (TypeIt == KnownType.end() ||
-          LookUpFieldOffset(*TypeIt->second, Split.second, Offset)) {
+          lookUpField(*TypeIt->second, Split.second, Type, Offset)) {
         std::pair BaseMember = Split.second.split('.');
         StringRef Base = BaseMember.first, Member = BaseMember.second;
-        LookUpFieldOffset(Base, Member, Offset);
+        lookUpField(Base, Member, Type, Offset);
       }
     }
 
@@ -6519,34 +6522,56 @@ static int rewritesSort(const AsmRewrite *AsmRewriteA,
   llvm_unreachable("Unstable rewrite sort.");
 }
 
-bool MasmParser::LookUpFieldOffset(StringRef Base, StringRef Member,
-                                   unsigned &Offset) {
+bool MasmParser::lookUpField(StringRef Name, StringRef &Type,
+                             unsigned &Offset) const {
+  const std::pair BaseMember = Name.split('.');
+  const StringRef Base = BaseMember.first, Member = BaseMember.second;
+  return lookUpField(Base, Member, Type, Offset);
+}
+
+bool MasmParser::lookUpField(StringRef Base, StringRef Member, StringRef &Type,
+                             unsigned &Offset) const {
   if (Base.empty())
     return true;
 
+  unsigned BaseOffset = 0;
+  if (Base.contains('.') && !lookUpField(Base, Type, BaseOffset))
+    Base = Type;
+
   auto TypeIt = KnownType.find(Base);
   if (TypeIt != KnownType.end())
-    return LookUpFieldOffset(*TypeIt->second, Member, Offset);
+    return lookUpField(*TypeIt->second, Member, Type, Offset);
 
   auto StructIt = Structs.find(Base.lower());
   if (StructIt != Structs.end())
-    return LookUpFieldOffset(StructIt->second, Member, Offset);
+    return lookUpField(StructIt->second, Member, Type, Offset);
 
   return true;
 }
 
-bool MasmParser::LookUpFieldOffset(const StructInfo &Structure,
-                                   StringRef Member, unsigned &Offset) {
+bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
+                             StringRef &Type, unsigned &Offset) const {
+  if (Member.empty()) {
+    Type = Structure.Name;
+    return false;
+  }
+
   std::pair Split = Member.split('.');
   const StringRef FieldName = Split.first, FieldMember = Split.second;
 
+  auto StructIt = Structs.find(FieldName.lower());
+  if (StructIt != Structs.end())
+    return lookUpField(StructIt->second, FieldMember, Type, Offset);
+
   auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
   if (FieldIt == Structure.FieldsByName.end())
     return true;
 
   const FieldInfo &Field = Structure.Fields[FieldIt->second];
   if (FieldMember.empty()) {
-    Offset = Field.Offset;
+    Offset += Field.Offset;
+    if (Field.Contents.FT == FT_STRUCT)
+      Type = Field.Contents.StructInfo.Structure.Name;
     return false;
   }
 
@@ -6554,7 +6579,7 @@ bool MasmParser::LookUpFieldOffset(const StructInfo &Structure,
     return true;
   const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
 
-  bool Result = LookUpFieldOffset(StructInfo.Structure, FieldMember, Offset);
+  bool Result = lookUpField(StructInfo.Structure, FieldMember, Type, Offset);
   if (Result)
     return true;
 
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 0573d4eec0599..fe09b2952f0e2 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -358,6 +358,7 @@ class X86AsmParser : public MCTargetAsmParser {
     bool MemExpr;
     bool OffsetOperator;
     SMLoc OffsetOperatorLoc;
+    StringRef CurType;
 
     bool setSymRef(const MCExpr *Val, StringRef ID, StringRef &ErrMsg) {
       if (Sym) {
@@ -385,6 +386,7 @@ class X86AsmParser : public MCTargetAsmParser {
     unsigned getScale() { return Scale; }
     const MCExpr *getSym() { return Sym; }
     StringRef getSymName() { return SymName; }
+    StringRef getType() { return CurType; }
     int64_t getImm() { return Imm + IC.execute(); }
     bool isValidEndState() {
       return State == IES_RBRAC || State == IES_INTEGER;
@@ -846,6 +848,7 @@ class X86AsmParser : public MCTargetAsmParser {
       }
       return false;
     }
+    void setType(StringRef Type) { CurType = Type; }
   };
 
   bool Error(SMLoc L, const Twine &Msg, SMRange Range = None,
@@ -1641,27 +1644,25 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
           break;
         }
         if (Parser.isParsingMasm()) {
-          const std::pair RegField =
+          const std::pair IDField =
               Tok.getString().split('.');
-          const StringRef RegName = RegField.first, Field = RegField.second;
-          SMLoc RegEndLoc =
-              SMLoc::getFromPointer(RegName.data() + RegName.size());
+          const StringRef ID = IDField.first, Field = IDField.second;
+          SMLoc IDEndLoc = SMLoc::getFromPointer(ID.data() + ID.size());
           if (!Field.empty() &&
-              !MatchRegisterByName(Reg, RegName, IdentLoc, RegEndLoc)) {
+              !MatchRegisterByName(Reg, ID, IdentLoc, IDEndLoc)) {
             if (SM.onRegister(Reg, ErrMsg))
               return Error(IdentLoc, ErrMsg);
 
+            StringRef Type;
+            unsigned Offset = 0;
             SMLoc FieldStartLoc = SMLoc::getFromPointer(Field.data());
-            const std::pair BaseMember = Field.split('.');
-            const StringRef Base = BaseMember.first, Member = BaseMember.second;
-
-            unsigned Offset;
-            if (Parser.LookUpFieldOffset(Base, Member, Offset))
+            if (Parser.lookUpField(Field, Type, Offset))
               return Error(FieldStartLoc, "unknown offset");
             else if (SM.onPlus(ErrMsg))
               return Error(getTok().getLoc(), ErrMsg);
             else if (SM.onInteger(Offset, ErrMsg))
               return Error(IdentLoc, ErrMsg);
+            SM.setType(Type);
 
             End = consumeToken();
             break;
@@ -1915,9 +1916,11 @@ X86AsmParser::ParseRoundingModeOp(SMLoc Start) {
 }
 
 /// Parse the '.' operator.
-bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End) {
+bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM,
+                                         SMLoc &End) {
   const AsmToken &Tok = getTok();
-  unsigned Offset;
+  StringRef Type;
+  unsigned Offset = 0;
 
   // Drop the optional '.'.
   StringRef DotDispStr = Tok.getString();
@@ -1933,8 +1936,9 @@ bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End)
              Tok.is(AsmToken::Identifier)) {
     const std::pair BaseMember = DotDispStr.split('.');
     const StringRef Base = BaseMember.first, Member = BaseMember.second;
-    if (getParser().LookUpFieldOffset(SM.getSymName(), DotDispStr, Offset) &&
-        getParser().LookUpFieldOffset(Base, Member, Offset) &&
+    if (getParser().lookUpField(SM.getType(), DotDispStr, Type, Offset) &&
+        getParser().lookUpField(SM.getSymName(), DotDispStr, Type, Offset) &&
+        getParser().lookUpField(DotDispStr, Type, Offset) &&
         (!SemaCallback ||
          SemaCallback->LookupInlineAsmField(Base, Member, Offset)))
       return Error(Tok.getLoc(), "Unable to lookup field reference!");
@@ -1947,6 +1951,7 @@ bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End)
   while (Tok.getLoc().getPointer() < DotExprEndLoc)
     Lex();
   SM.addImm(Offset);
+  SM.setType(Type);
   return false;
 }
 
diff --git a/llvm/test/tools/llvm-ml/struct.test b/llvm/test/tools/llvm-ml/struct.test
index 0e60d24494555..ecd89a140371b 100644
--- a/llvm/test/tools/llvm-ml/struct.test
+++ b/llvm/test/tools/llvm-ml/struct.test
@@ -85,13 +85,11 @@ t3:
 mov eax, t2.f.h
 mov eax, [t2].f.h
 mov eax, [t2.f.h]
-mov eax, t2.FOOBAR.f.h
 
 ; CHECK: t3:
 ; CHECK-NEXT: mov eax, dword ptr [rip + t2+12]
 ; CHECK-NEXT: mov eax, dword ptr [rip + t2+12]
 ; CHECK-NEXT: mov eax, dword ptr [rip + t2+12]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+12]
 
 t4:
 mov eax, j.FOOBAR.f.h
@@ -101,4 +99,52 @@ mov eax, j.baz.b
 ; CHECK-NEXT: mov eax, dword ptr [rip + j+12]
 ; CHECK-NEXT: mov eax, dword ptr [rip + j+1]
 
+t5:
+mov eax, [ebx].FOOBAR.f.h
+mov eax, [ebx.FOOBAR].f.h
+mov eax, [ebx.FOOBAR.f.h]
+
+; CHECK: t5:
+; CHECK-NEXT: mov eax, dword ptr [ebx + 12]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 12]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 12]
+
+t6:
+mov eax, t2.FOOBAR.f.h
+mov eax, [t2].FOOBAR.f.h
+mov eax, [t2.FOOBAR].f.h
+mov eax, [t2.FOOBAR.f.h]
+
+; CHECK: t6:
+; CHECK-NEXT: mov eax, dword ptr [rip + t2+12]
+; CHECK-NEXT: mov eax, dword ptr [rip + t2+12]
+; CHECK-NEXT: mov eax, dword ptr [rip + t2+12]
+; CHECK-NEXT: mov eax, dword ptr [rip + t2+12]
+
+t7:
+mov eax, [ebx].FOOBAR.e.b
+mov eax, [ebx.FOOBAR].e.b
+mov eax, [ebx.FOOBAR.e].b
+mov eax, [ebx.FOOBAR.e.b]
+
+; CHECK: t7:
+; CHECK-NEXT: mov eax, dword ptr [ebx + 9]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 9]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 9]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 9]
+
+t8:
+mov eax, t2.FOOBAR.e.b
+mov eax, [t2].FOOBAR.e.b
+mov eax, [t2.FOOBAR].e.b
+mov eax, [t2.FOOBAR.e].b
+mov eax, [t2.FOOBAR.e.b]
+
+; CHECK: t8:
+; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
+; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
+; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
+; CHECK-NEXT: mov eax, dword ptr [rip + (t2+8)+1]
+; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
+
 END

From 7f85e9808255f3f6c2dda81d834f9de1feb827c6 Mon Sep 17 00:00:00 2001
From: Eric Astor 
Date: Mon, 13 Jul 2020 10:36:30 -0400
Subject: [PATCH 104/771] [ms] [llvm-ml] Fix MASM support for nested unnamed
 STRUCTs and UNIONs

Summary: Fix MASM support for nested unnamed STRUCTs and UNIONs

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D83345
---
 llvm/lib/MC/MCParser/MasmParser.cpp | 67 ++++++++++++++++++-----------
 llvm/test/tools/llvm-ml/struct.test | 29 +++++++++++++
 2 files changed, 71 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index d7d0508cabff7..58c22b2ccef26 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -4084,11 +4084,8 @@ bool MasmParser::parseDirectiveEnds(StringRef Name, SMLoc NameLoc) {
     return Error(NameLoc, "mismatched name in ENDS directive; expected '" +
                               StructInProgress.back().Name + "'");
   StructInfo Structure = StructInProgress.pop_back_val();
-  if (Structure.Size % Structure.Alignment != 0) {
-    // Pad to make the structure's size divisible by its alignment.
-    Structure.Size +=
-        Structure.Alignment - (Structure.Size % Structure.Alignment);
-  }
+  // Pad to make the structure's size divisible by its alignment.
+  Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
   Structs[Name.lower()] = Structure;
 
   if (parseToken(AsmToken::EndOfStatement))
@@ -4107,29 +4104,49 @@ bool MasmParser::parseDirectiveNestedEnds() {
     return addErrorSuffix(" in nested ENDS directive");
 
   StructInfo Structure = StructInProgress.pop_back_val();
-  if (Structure.Size % Structure.Alignment != 0) {
-    // Pad to make the structure's size divisible by its alignment.
-    Structure.Size +=
-        Structure.Alignment - (Structure.Size % Structure.Alignment);
-  }
-  StructInfo &ParentStruct = StructInProgress.back();
+  // Pad to make the structure's size divisible by its alignment.
+  Structure.Size = llvm::alignTo(Structure.Size, Structure.Alignment);
 
-  FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT);
-  StructFieldInfo &StructInfo = Field.Contents.StructInfo;
-  Field.Type = Structure.Size;
-  Field.LengthOf = 1;
-  Field.SizeOf = Structure.Size;
+  StructInfo &ParentStruct = StructInProgress.back();
+  if (Structure.Name.empty()) {
+    const size_t OldFields = ParentStruct.Fields.size();
+    ParentStruct.Fields.insert(
+        ParentStruct.Fields.end(),
+        std::make_move_iterator(Structure.Fields.begin()),
+        std::make_move_iterator(Structure.Fields.end()));
+    for (const auto &FieldByName : Structure.FieldsByName) {
+      ParentStruct.FieldsByName[FieldByName.getKey()] =
+          FieldByName.getValue() + OldFields;
+    }
+    if (!ParentStruct.IsUnion) {
+      for (auto FieldIter = ParentStruct.Fields.begin() + OldFields;
+           FieldIter != ParentStruct.Fields.end(); ++FieldIter) {
+        FieldIter->Offset += ParentStruct.Size;
+      }
+    }
 
-  if (ParentStruct.IsUnion)
-    ParentStruct.Size = std::max(ParentStruct.Size, Field.SizeOf);
-  else
-    ParentStruct.Size += Field.SizeOf;
+    if (ParentStruct.IsUnion)
+      ParentStruct.Size = std::max(ParentStruct.Size, Structure.Size);
+    else
+      ParentStruct.Size += Structure.Size;
+  } else {
+    FieldInfo &Field = ParentStruct.addField(Structure.Name, FT_STRUCT);
+    StructFieldInfo &StructInfo = Field.Contents.StructInfo;
+    Field.Type = Structure.Size;
+    Field.LengthOf = 1;
+    Field.SizeOf = Structure.Size;
+
+    if (ParentStruct.IsUnion)
+      ParentStruct.Size = std::max(ParentStruct.Size, Field.SizeOf);
+    else
+      ParentStruct.Size += Field.SizeOf;
 
-  StructInfo.Structure = Structure;
-  StructInfo.Initializers.emplace_back();
-  auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
-  for (const auto &SubField : Structure.Fields) {
-    FieldInitializers.push_back(SubField.Contents);
+    StructInfo.Structure = Structure;
+    StructInfo.Initializers.emplace_back();
+    auto &FieldInitializers = StructInfo.Initializers.back().FieldInitializers;
+    for (const auto &SubField : Structure.Fields) {
+      FieldInitializers.push_back(SubField.Contents);
+    }
   }
 
   return false;
diff --git a/llvm/test/tools/llvm-ml/struct.test b/llvm/test/tools/llvm-ml/struct.test
index ecd89a140371b..7bdbf51b7114e 100644
--- a/llvm/test/tools/llvm-ml/struct.test
+++ b/llvm/test/tools/llvm-ml/struct.test
@@ -147,4 +147,33 @@ mov eax, [t2.FOOBAR.e.b]
 ; CHECK-NEXT: mov eax, dword ptr [rip + (t2+8)+1]
 ; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
 
+QUUX STRUCT
+  u DWORD ?
+  UNION
+    v WORD ?
+    w DWORD ?
+    STRUCT
+      x BYTE ?
+      y BYTE ?
+    ENDS
+  ENDS
+  z DWORD ?
+QUUX ENDS
+
+t9:
+mov eax, [ebx].QUUX.u
+mov eax, [ebx].QUUX.v
+mov eax, [ebx].QUUX.w
+mov eax, [ebx].QUUX.x
+mov eax, [ebx].QUUX.y
+mov eax, [ebx].QUUX.z
+
+; CHECK: t9:
+; CHECK-NEXT: mov eax, dword ptr [ebx]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 5]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 8]
+
 END

From 835c1f9f40ecc1a725f8f392a2a1628f634479fe Mon Sep 17 00:00:00 2001
From: Jinsong Ji 
Date: Mon, 13 Jul 2020 02:54:20 +0000
Subject: [PATCH 105/771] [compiler-rt][CMake] Pass down LLVM_LIT_ARGS in
 runtime build

We should also pass down the LLVM_LIT_ARGS in runtime build mode,
so that the runtime tests can be well controlled as well.

We actually passed this down in clang/runtime/CMakeLists.txt
But not for calls from llvm/runtime/CMakeLists.txt.

Reviewed By: phosek

Differential Revision: https://reviews.llvm.org/D83565
---
 llvm/cmake/modules/LLVMExternalProjectUtils.cmake | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/cmake/modules/LLVMExternalProjectUtils.cmake b/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
index 4eb5fad85634b..706a1ffb5c7b7 100644
--- a/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
+++ b/llvm/cmake/modules/LLVMExternalProjectUtils.cmake
@@ -250,6 +250,7 @@ function(llvm_ExternalProject_Add name source_dir)
                -DLLVM_HAVE_LINK_VERSION_SCRIPT=${LLVM_HAVE_LINK_VERSION_SCRIPT}
                -DLLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO=${LLVM_USE_RELATIVE_PATHS_IN_DEBUG_INFO}
                -DLLVM_USE_RELATIVE_PATHS_IN_FILES=${LLVM_USE_RELATIVE_PATHS_IN_FILES}
+               -DLLVM_LIT_ARGS=${LLVM_LIT_ARGS}
                -DLLVM_SOURCE_PREFIX=${LLVM_SOURCE_PREFIX}
                -DPACKAGE_VERSION=${PACKAGE_VERSION}
                -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}

From f08e8b6d7c46334ff8aa37cf8e473aa405e4fa93 Mon Sep 17 00:00:00 2001
From: Eric Astor 
Date: Mon, 13 Jul 2020 10:38:39 -0400
Subject: [PATCH 106/771] [ms] [llvm-ml] Add support for MASM STRUCT casting
 field accessors: ( PTR ).

Summary:
Add support for MASM STRUCT casting field accessors: ( PTR ).

Since these are operands, we add them to X86AsmParser. If/when we extend MASM support to other architectures (e.g., ARM), we will need similar changes there as well.

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D83346
---
 .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 31 ++++++++++++++++++-
 llvm/test/tools/llvm-ml/struct.test           | 16 ++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index fe09b2952f0e2..fc8813e79a3ed 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -332,6 +332,7 @@ class X86AsmParser : public MCTargetAsmParser {
     IES_PLUS,
     IES_MINUS,
     IES_OFFSET,
+    IES_CAST,
     IES_NOT,
     IES_MULTIPLY,
     IES_DIVIDE,
@@ -632,6 +633,7 @@ class X86AsmParser : public MCTargetAsmParser {
       default:
         State = IES_ERROR;
         break;
+      case IES_CAST:
       case IES_PLUS:
       case IES_MINUS:
       case IES_NOT:
@@ -744,6 +746,7 @@ class X86AsmParser : public MCTargetAsmParser {
         IC.pushOperator(IC_PLUS);
         break;
       case IES_INIT:
+      case IES_CAST:
         assert(!BracCount && "BracCount should be zero on parsing's start");
         State = IES_LBRAC;
         break;
@@ -816,6 +819,7 @@ class X86AsmParser : public MCTargetAsmParser {
       case IES_INTEGER:
       case IES_OFFSET:
       case IES_REGISTER:
+      case IES_RBRAC:
       case IES_RPAREN:
         State = IES_RPAREN;
         IC.pushOperator(IC_RPAREN);
@@ -848,6 +852,18 @@ class X86AsmParser : public MCTargetAsmParser {
       }
       return false;
     }
+    void onCast(StringRef Type) {
+      PrevState = State;
+      switch (State) {
+      default:
+        State = IES_ERROR;
+        break;
+      case IES_LPAREN:
+        setType(Type);
+        State = IES_CAST;
+        break;
+      }
+    }
     void setType(StringRef Type) { CurType = Type; }
   };
 
@@ -1635,6 +1651,18 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
       SMLoc IdentLoc = Tok.getLoc();
       StringRef Identifier = Tok.getString();
       UpdateLocLex = false;
+      // (MASM only)  PTR operator
+      if (Parser.isParsingMasm()) {
+        const AsmToken &NextTok = getLexer().peekTok();
+        if (NextTok.is(AsmToken::Identifier) &&
+            NextTok.getIdentifier().equals_lower("ptr")) {
+          SM.onCast(Identifier);
+          // eat type and ptr
+          consumeToken();
+          End = consumeToken();
+          break;
+        }
+      }
       // Register, or (MASM only) .
       unsigned Reg;
       if (Tok.is(AsmToken::Identifier)) {
@@ -1681,7 +1709,8 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
       const MCExpr *Val;
       if (isParsingMSInlineAsm() || Parser.isParsingMasm()) {
         // MS Dot Operator expression
-        if (Identifier.count('.') && PrevTK == AsmToken::RBrac) {
+        if (Identifier.count('.') &&
+            (PrevTK == AsmToken::RBrac || PrevTK == AsmToken::RParen)) {
           if (ParseIntelDotOperator(SM, End))
             return true;
           break;
diff --git a/llvm/test/tools/llvm-ml/struct.test b/llvm/test/tools/llvm-ml/struct.test
index 7bdbf51b7114e..3971cfd6eb237 100644
--- a/llvm/test/tools/llvm-ml/struct.test
+++ b/llvm/test/tools/llvm-ml/struct.test
@@ -176,4 +176,20 @@ mov eax, [ebx].QUUX.z
 ; CHECK-NEXT: mov eax, dword ptr [ebx + 5]
 ; CHECK-NEXT: mov eax, dword ptr [ebx + 8]
 
+t10:
+mov eax, FOOBAR.f
+mov eax, FOOBAR.f.h
+
+; CHECK: t10:
+; CHECK-NEXT: mov eax, 10
+; CHECK-NEXT: mov eax, 12
+
+t11:
+mov eax, (FOOBAR PTR [ebx]).f
+mov eax, (FOOBAR PTR t1).f
+
+; CHECK: t11:
+; CHECK-NEXT: mov eax, dword ptr [ebx + 10]
+; CHECK-NEXT: mov eax, dword ptr [rip + t1+10]
+
 END

From 1847f4dd7570f01f70646cd5067dd0c34257cd21 Mon Sep 17 00:00:00 2001
From: Pavel Labath 
Date: Wed, 8 Jul 2020 15:43:07 +0200
Subject: [PATCH 107/771] [lldb/Utility] Rewrite Scalar::SetValueFromCString

The function's reliance on host types meant that it was needlessly
complicated, and did not handle the newer (wider) types. Rewrite it in
terms of APInt/APFloat functions to save code and improve functionality.
---
 lldb/source/Utility/Scalar.cpp        | 153 +++++++++-----------------
 lldb/unittests/Utility/ScalarTest.cpp |  14 +++
 2 files changed, 63 insertions(+), 104 deletions(-)

diff --git a/lldb/source/Utility/Scalar.cpp b/lldb/source/Utility/Scalar.cpp
index 87ac6c23892d8..6c48bbde532f9 100644
--- a/lldb/source/Utility/Scalar.cpp
+++ b/lldb/source/Utility/Scalar.cpp
@@ -24,6 +24,7 @@ using namespace lldb;
 using namespace lldb_private;
 
 using llvm::APFloat;
+using llvm::APInt;
 
 namespace {
 enum class Category { Void, Integral, Float };
@@ -1002,116 +1003,60 @@ Status Scalar::SetValueFromCString(const char *value_str, Encoding encoding,
     error.SetErrorString("Invalid encoding.");
     break;
 
-  case eEncodingUint:
-    if (byte_size <= sizeof(uint64_t)) {
-      uint64_t uval64;
-      if (!llvm::to_integer(value_str, uval64))
-        error.SetErrorStringWithFormat(
-            "'%s' is not a valid unsigned integer string value", value_str);
-      else if (!UIntValueIsValidForSize(uval64, byte_size))
-        error.SetErrorStringWithFormat(
-            "value 0x%" PRIx64 " is too large to fit in a %" PRIu64
-            " byte unsigned integer value",
-            uval64, static_cast(byte_size));
-      else {
-        m_type = Scalar::GetValueTypeForUnsignedIntegerWithByteSize(byte_size);
-        switch (m_type) {
-        case e_uint:
-          m_integer = llvm::APInt(sizeof(uint_t) * 8, uval64, false);
-          break;
-        case e_ulong:
-          m_integer = llvm::APInt(sizeof(ulong_t) * 8, uval64, false);
-          break;
-        case e_ulonglong:
-          m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, uval64, false);
-          break;
-        default:
-          error.SetErrorStringWithFormat(
-              "unsupported unsigned integer byte size: %" PRIu64 "",
-              static_cast(byte_size));
-          break;
-        }
-      }
-    } else {
-      error.SetErrorStringWithFormat(
-          "unsupported unsigned integer byte size: %" PRIu64 "",
-          static_cast(byte_size));
-      return error;
-    }
-    break;
-
   case eEncodingSint:
-    if (byte_size <= sizeof(int64_t)) {
-      int64_t sval64;
-      if (!llvm::to_integer(value_str, sval64))
-        error.SetErrorStringWithFormat(
-            "'%s' is not a valid signed integer string value", value_str);
-      else if (!SIntValueIsValidForSize(sval64, byte_size))
-        error.SetErrorStringWithFormat(
-            "value 0x%" PRIx64 " is too large to fit in a %" PRIu64
-            " byte signed integer value",
-            sval64, static_cast(byte_size));
-      else {
-        m_type = Scalar::GetValueTypeForSignedIntegerWithByteSize(byte_size);
-        switch (m_type) {
-        case e_sint:
-          m_integer = llvm::APInt(sizeof(sint_t) * 8, sval64, true);
-          break;
-        case e_slong:
-          m_integer = llvm::APInt(sizeof(slong_t) * 8, sval64, true);
-          break;
-        case e_slonglong:
-          m_integer = llvm::APInt(sizeof(slonglong_t) * 8, sval64, true);
-          break;
-        default:
-          error.SetErrorStringWithFormat(
-              "unsupported signed integer byte size: %" PRIu64 "",
-              static_cast(byte_size));
-          break;
-        }
-      }
-    } else {
-      error.SetErrorStringWithFormat(
-          "unsupported signed integer byte size: %" PRIu64 "",
-          static_cast(byte_size));
-      return error;
+  case eEncodingUint: {
+    llvm::StringRef str = value_str;
+    bool is_signed = encoding == eEncodingSint;
+    bool is_negative = is_signed && str.consume_front("-");
+    APInt integer;
+    if (str.getAsInteger(0, integer)) {
+      error.SetErrorStringWithFormatv(
+          "'{0}' is not a valid integer string value", value_str);
+      break;
+    }
+    bool fits;
+    if (is_signed) {
+      integer = integer.zext(integer.getBitWidth() + 1);
+      if (is_negative)
+        integer.negate();
+      fits = integer.isSignedIntN(byte_size * 8);
+    } else
+      fits = integer.isIntN(byte_size * 8);
+    if (!fits) {
+      error.SetErrorStringWithFormatv(
+          "value {0} is too large to fit in a {1} byte integer value",
+          value_str, byte_size);
+      break;
+    }
+    m_type = GetBestTypeForBitSize(8 * byte_size, is_signed);
+    if (m_type == e_void) {
+      error.SetErrorStringWithFormatv("unsupported integer byte size: {0}",
+                                      byte_size);
+      break;
     }
+    if (is_signed)
+      m_integer = integer.sextOrTrunc(GetBitSize(m_type));
+    else
+      m_integer = integer.zextOrTrunc(GetBitSize(m_type));
     break;
+  }
 
-  case eEncodingIEEE754:
-    static float f_val;
-    static double d_val;
-    static long double l_val;
-    if (byte_size == sizeof(float)) {
-      if (::sscanf(value_str, "%f", &f_val) == 1) {
-        m_float = llvm::APFloat(f_val);
-        m_type = e_float;
-      } else
-        error.SetErrorStringWithFormat("'%s' is not a valid float string value",
-                                       value_str);
-    } else if (byte_size == sizeof(double)) {
-      if (::sscanf(value_str, "%lf", &d_val) == 1) {
-        m_float = llvm::APFloat(d_val);
-        m_type = e_double;
-      } else
-        error.SetErrorStringWithFormat("'%s' is not a valid float string value",
-                                       value_str);
-    } else if (byte_size == sizeof(long double)) {
-      if (::sscanf(value_str, "%Lf", &l_val) == 1) {
-        m_float = llvm::APFloat(
-            llvm::APFloat::x87DoubleExtended(),
-            llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128,
-                        (reinterpret_cast(&l_val))->x));
-        m_type = e_long_double;
-      } else
-        error.SetErrorStringWithFormat("'%s' is not a valid float string value",
-                                       value_str);
-    } else {
-      error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "",
-                                     static_cast(byte_size));
-      return error;
+  case eEncodingIEEE754: {
+    Type type = GetValueTypeForFloatWithByteSize(byte_size);
+    if (type == e_void) {
+      error.SetErrorStringWithFormatv("unsupported float byte size: {0}",
+                                      byte_size);
+      break;
     }
+    APFloat f(GetFltSemantics(type));
+    if (llvm::Expected op =
+            f.convertFromString(value_str, APFloat::rmNearestTiesToEven)) {
+      m_type = type;
+      m_float = std::move(f);
+    } else
+      error = op.takeError();
     break;
+  }
 
   case eEncodingVector:
     error.SetErrorString("vector encoding unsupported.");
diff --git a/lldb/unittests/Utility/ScalarTest.cpp b/lldb/unittests/Utility/ScalarTest.cpp
index 42a2f2aaebf2f..dd4683145b968 100644
--- a/lldb/unittests/Utility/ScalarTest.cpp
+++ b/lldb/unittests/Utility/ScalarTest.cpp
@@ -334,6 +334,20 @@ TEST(ScalarTest, SetValueFromCString) {
   EXPECT_THAT_ERROR(
       a.SetValueFromCString("-123", lldb::eEncodingUint, 8).ToError(),
       Failed());
+  EXPECT_THAT_ERROR(
+      a.SetValueFromCString("-2147483648", lldb::eEncodingSint, 4).ToError(),
+      Succeeded());
+  EXPECT_EQ(-2147483648, a);
+  EXPECT_THAT_ERROR(
+      a.SetValueFromCString("-2147483649", lldb::eEncodingSint, 4).ToError(),
+      Failed());
+  EXPECT_THAT_ERROR(
+      a.SetValueFromCString("47.25", lldb::eEncodingIEEE754, 4).ToError(),
+      Succeeded());
+  EXPECT_EQ(47.25f, a);
+  EXPECT_THAT_ERROR(
+      a.SetValueFromCString("asdf", lldb::eEncodingIEEE754, 4).ToError(),
+      Failed());
 }
 
 TEST(ScalarTest, APIntConstructor) {

From 3aabfa28086757f8469ead77c7d319302e49d3c8 Mon Sep 17 00:00:00 2001
From: Eric Astor 
Date: Mon, 13 Jul 2020 10:47:30 -0400
Subject: [PATCH 108/771] [ms] [llvm-ml] Restore omitted changes requested by
 reviewer

---
 llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 2 +-
 llvm/test/tools/llvm-ml/struct.test            | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index fc8813e79a3ed..a3014b2aba92c 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -1657,7 +1657,7 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
         if (NextTok.is(AsmToken::Identifier) &&
             NextTok.getIdentifier().equals_lower("ptr")) {
           SM.onCast(Identifier);
-          // eat type and ptr
+          // Eat type and PTR.
           consumeToken();
           End = consumeToken();
           break;
diff --git a/llvm/test/tools/llvm-ml/struct.test b/llvm/test/tools/llvm-ml/struct.test
index 3971cfd6eb237..fa85ecd455dda 100644
--- a/llvm/test/tools/llvm-ml/struct.test
+++ b/llvm/test/tools/llvm-ml/struct.test
@@ -156,6 +156,7 @@ QUUX STRUCT
       x BYTE ?
       y BYTE ?
     ENDS
+    after_struct BYTE ?
   ENDS
   z DWORD ?
 QUUX ENDS
@@ -166,6 +167,7 @@ mov eax, [ebx].QUUX.v
 mov eax, [ebx].QUUX.w
 mov eax, [ebx].QUUX.x
 mov eax, [ebx].QUUX.y
+mov eax, [ebx].QUUX.after_struct
 mov eax, [ebx].QUUX.z
 
 ; CHECK: t9:
@@ -174,6 +176,7 @@ mov eax, [ebx].QUUX.z
 ; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
 ; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
 ; CHECK-NEXT: mov eax, dword ptr [ebx + 5]
+; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
 ; CHECK-NEXT: mov eax, dword ptr [ebx + 8]
 
 t10:

From 7075c056e91bf95b111716a9722d10e1a61253bb Mon Sep 17 00:00:00 2001
From: Alexey Bataev 
Date: Thu, 9 Jul 2020 08:34:06 -0400
Subject: [PATCH 109/771] [OPENMP]Fix compiler crash for target data directive
 without actual target codegen.

Summary:
Need to privatize addresses of the captured variables when trying to
emit the body of the target data directive in no target codegen mode.

Reviewers: jdoerfert

Subscribers: yaxunl, guansong, cfe-commits, sstefan1, caomhin

Tags: #clang

Differential Revision: https://reviews.llvm.org/D83478
---
 clang/lib/CodeGen/CGStmtOpenMP.cpp        |  1 +
 clang/test/OpenMP/target_data_codegen.cpp | 19 +++++++++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 7135135d2a410..cfd5eda8cc80b 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -6077,6 +6077,7 @@ void CodeGenFunction::EmitOMPTargetDataDirective(
         (void)PrivateScope.Privatize();
         RCG(CGF);
       } else {
+        OMPLexicalScope Scope(CGF, S, OMPD_unknown);
         RCG(CGF);
       }
     };
diff --git a/clang/test/OpenMP/target_data_codegen.cpp b/clang/test/OpenMP/target_data_codegen.cpp
index f1c9f621bf748..f9257615ce405 100644
--- a/clang/test/OpenMP/target_data_codegen.cpp
+++ b/clang/test/OpenMP/target_data_codegen.cpp
@@ -491,4 +491,23 @@ void test_close_modifier(int arg) {
   {++arg;}
 }
 #endif
+///==========================================================================///
+// RUN: %clang_cc1 -DCK7 -verify -fopenmp -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix CK7 --check-prefix CK7-64
+// RUN: %clang_cc1 -DCK7 -fopenmp -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s  --check-prefix CK7 --check-prefix CK7-64
+
+// RUN: %clang_cc1 -DCK7 -verify -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY7 %s
+// RUN: %clang_cc1 -DCK7 -fopenmp-simd -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY7 %s
+// SIMD-ONLY7-NOT: {{__kmpc|__tgt}}
+#ifdef CK7
+// CK7: test_device_ptr_addr
+void test_device_ptr_addr(int arg) {
+  int *p;
+  // CK7: add nsw i32
+  // CK7: add nsw i32
+  #pragma omp target data use_device_ptr(p) use_device_addr(arg)
+  { ++arg, ++(*p); }
+}
+#endif
 #endif

From 4121172239779ea509908a2a57278a3d2206ad92 Mon Sep 17 00:00:00 2001
From: David Truby 
Date: Mon, 13 Jul 2020 16:07:22 +0100
Subject: [PATCH 110/771] [flang][openmp] libc++ unordered_map build fix in
 flang openmp static analysis

Simply move the include of unordered_map from the .cpp file to the .h file
---
 flang/lib/Semantics/check-omp-structure.cpp | 1 -
 flang/lib/Semantics/check-omp-structure.h   | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index a5f65bcbc8044..d857d36ed05d9 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -9,7 +9,6 @@
 #include "check-omp-structure.h"
 #include "flang/Parser/parse-tree.h"
 #include "flang/Semantics/tools.h"
-#include 
 
 namespace Fortran::semantics {
 
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index eff0eb4aa76be..7fe78a792f19b 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -19,6 +19,8 @@
 #include "flang/Semantics/semantics.h"
 #include "llvm/Frontend/OpenMP/OMPConstants.h"
 
+#include 
+
 using OmpDirectiveSet = Fortran::common::EnumSet;
 

From 4d3e8dc215d1ca99354f3c33cce87795d2b5098a Mon Sep 17 00:00:00 2001
From: Sanne Wouda 
Date: Mon, 13 Jul 2020 16:09:41 +0100
Subject: [PATCH 111/771] Fix llvm-test-suite failure introduced by
 D82550/D83122

Apparently, isIndirectCall does not imply that getCalledFunction will be non-null
---
 llvm/include/llvm/Analysis/VectorUtils.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h
index ce8327ae43a80..b1d7850442fba 100644
--- a/llvm/include/llvm/Analysis/VectorUtils.h
+++ b/llvm/include/llvm/Analysis/VectorUtils.h
@@ -224,7 +224,7 @@ class VFDatabase {
   /// a vector Function ABI.
   static void getVFABIMappings(const CallInst &CI,
                                SmallVectorImpl &Mappings) {
-    if (CI.isIndirectCall())
+    if (!CI.getCalledFunction())
       return;
 
     const StringRef ScalarName = CI.getCalledFunction()->getName();

From a2552f76ac6ff705434adb1d277a578445721b78 Mon Sep 17 00:00:00 2001
From: Pavel Labath 
Date: Mon, 13 Jul 2020 17:15:25 +0200
Subject: [PATCH 112/771] [ADT] Make Load(AP)IntFromMemory pointer argument
 const

The function does not modify this memory.
---
 llvm/include/llvm/ADT/APInt.h | 2 +-
 llvm/lib/Support/APInt.cpp    | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index c88d9651d68da..f7df648d27ed6 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -2286,7 +2286,7 @@ void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst, unsigned StoreBytes);
 
 /// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
 /// from Src into IntVal, which is assumed to be wide enough and to hold zero.
-void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes);
+void LoadIntFromMemory(APInt &IntVal, const uint8_t *Src, unsigned LoadBytes);
 
 } // namespace llvm
 
diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp
index 4a591efb141aa..9a6f93feaa29f 100644
--- a/llvm/lib/Support/APInt.cpp
+++ b/llvm/lib/Support/APInt.cpp
@@ -3086,7 +3086,8 @@ void llvm::StoreIntToMemory(const APInt &IntVal, uint8_t *Dst,
 
 /// LoadIntFromMemory - Loads the integer stored in the LoadBytes bytes starting
 /// from Src into IntVal, which is assumed to be wide enough and to hold zero.
-void llvm::LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) {
+void llvm::LoadIntFromMemory(APInt &IntVal, const uint8_t *Src,
+                             unsigned LoadBytes) {
   assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!");
   uint8_t *Dst = reinterpret_cast(
                    const_cast(IntVal.getRawData()));

From a7e9c5a39fbc7939dbeb508bb446a6ceaab2dc4b Mon Sep 17 00:00:00 2001
From: stevewan 
Date: Mon, 13 Jul 2020 11:58:22 -0400
Subject: [PATCH 113/771] [llvm-ar][test][AIX] Unsupport
 error-opening-directory.test on AIX

Summary:
The test fails on AIX as it allows open() and read() on a directory. This patch adds `# UNSUPPORTED:
system-aix` to the test to prevent it from running on AIX.

Reviewers: sameerarora101, daltenty, ShuhongL, hubert.reinterpretcast, MaskRay, smeenai, alexshap

Reviewed By: sameerarora101, hubert.reinterpretcast, MaskRay, smeenai

Subscribers: MaskRay, rupprecht, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D83579
---
 llvm/test/tools/llvm-ar/error-opening-directory.test | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/test/tools/llvm-ar/error-opening-directory.test b/llvm/test/tools/llvm-ar/error-opening-directory.test
index 1f19da7543b3d..c3068871230fc 100644
--- a/llvm/test/tools/llvm-ar/error-opening-directory.test
+++ b/llvm/test/tools/llvm-ar/error-opening-directory.test
@@ -1,6 +1,6 @@
-## Unsupported on FreeBSD as FreeBSD 12 and earlier allow reading directories
-## by default.
-# UNSUPPORTED: system-freebsd
+## Unsupported on AIX and FreeBSD as AIX and FreeBSD 12 and earlier allow
+## reading directories by default.
+# UNSUPPORTED: system-freebsd, system-aix
 
 # RUN: rm -rf %t && mkdir -p %t
 

From 8f7d3430b72e0458f0917b605cd94bcfb9396b37 Mon Sep 17 00:00:00 2001
From: Pavel Iliin 
Date: Mon, 13 Jul 2020 12:37:59 +0100
Subject: [PATCH 114/771] [ARM][NFC] More detailed vbsl checks in ARM & Thumb2
 tests.

---
 llvm/test/CodeGen/ARM/fcopysign.ll            |  96 +++-
 llvm/test/CodeGen/ARM/fp16-promote.ll         |  46 +-
 llvm/test/CodeGen/ARM/vbsl-constant.ll        | 104 +++--
 llvm/test/CodeGen/ARM/vbsl.ll                 | 205 +++++++--
 llvm/test/CodeGen/ARM/vselect_imax.ll         | 434 +++++++++++++++++-
 .../CodeGen/Thumb2/float-intrinsics-double.ll |   8 +-
 .../CodeGen/Thumb2/float-intrinsics-float.ll  |  20 +-
 7 files changed, 795 insertions(+), 118 deletions(-)

diff --git a/llvm/test/CodeGen/ARM/fcopysign.ll b/llvm/test/CodeGen/ARM/fcopysign.ll
index d013fbf8c15ac..05dbb65a6deba 100644
--- a/llvm/test/CodeGen/ARM/fcopysign.ll
+++ b/llvm/test/CodeGen/ARM/fcopysign.ll
@@ -1,40 +1,70 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -disable-post-ra -mtriple=armv7-apple-darwin -mcpu=cortex-a8 | FileCheck %s -check-prefix=SOFT
 ; RUN: llc < %s -disable-post-ra -mtriple=armv7-gnueabi -float-abi=hard -mcpu=cortex-a8 | FileCheck %s -check-prefix=HARD
 
 ; rdar://8984306
 define float @test1(float %x, float %y) nounwind {
-entry:
 ; SOFT-LABEL: test1:
-; SOFT: lsr r1, r1, #31
-; SOFT: bfi r0, r1, #31, #1
-
+; SOFT:       @ %bb.0: @ %entry
+; SOFT-NEXT:    lsr r1, r1, #31
+; SOFT-NEXT:    bfi r0, r1, #31, #1
+; SOFT-NEXT:    bx lr
+;
 ; HARD-LABEL: test1:
-; HARD: vmov.i32 [[REG1:(d[0-9]+)]], #0x80000000
-; HARD: vbsl [[REG1]], d
+; HARD:       @ %bb.0: @ %entry
+; HARD-NEXT:    vmov.f32 s4, s1
+; HARD-NEXT:    @ kill: def $s0 killed $s0 def $d0
+; HARD-NEXT:    vmov.i32 d1, #0x80000000
+; HARD-NEXT:    vbsl d1, d2, d0
+; HARD-NEXT:    vmov.f32 s0, s2
+; HARD-NEXT:    bx lr
+entry:
+
   %0 = tail call float @copysignf(float %x, float %y) nounwind readnone
   ret float %0
 }
 
 define double @test2(double %x, double %y) nounwind {
-entry:
 ; SOFT-LABEL: test2:
-; SOFT: lsr r2, r3, #31
-; SOFT: bfi r1, r2, #31, #1
-
+; SOFT:       @ %bb.0: @ %entry
+; SOFT-NEXT:    lsr r2, r3, #31
+; SOFT-NEXT:    bfi r1, r2, #31, #1
+; SOFT-NEXT:    bx lr
+;
 ; HARD-LABEL: test2:
-; HARD: vmov.i32 [[REG2:(d[0-9]+)]], #0x80000000
-; HARD: vshl.i64 [[REG2]], [[REG2]], #32
-; HARD: vbsl [[REG2]], d1, d0
+; HARD:       @ %bb.0: @ %entry
+; HARD-NEXT:    vmov.i32 d16, #0x80000000
+; HARD-NEXT:    vshl.i64 d16, d16, #32
+; HARD-NEXT:    vbsl d16, d1, d0
+; HARD-NEXT:    vorr d0, d16, d16
+; HARD-NEXT:    bx lr
+entry:
+
   %0 = tail call double @copysign(double %x, double %y) nounwind readnone
   ret double %0
 }
 
 define double @test3(double %x, double %y, double %z) nounwind {
-entry:
 ; SOFT-LABEL: test3:
-; SOFT: vmov.i32 [[REG3:(d[0-9]+)]], #0x80000000
-; SOFT: vshl.i64 [[REG3]], [[REG3]], #32
-; SOFT: vbsl [[REG3]],
+; SOFT:       @ %bb.0: @ %entry
+; SOFT-NEXT:    vmov d16, r2, r3
+; SOFT-NEXT:    vmov d17, r0, r1
+; SOFT-NEXT:    vmul.f64 d16, d17, d16
+; SOFT-NEXT:    vmov.i32 d17, #0x80000000
+; SOFT-NEXT:    vshl.i64 d17, d17, #32
+; SOFT-NEXT:    vldr d18, [sp]
+; SOFT-NEXT:    vbsl d17, d18, d16
+; SOFT-NEXT:    vmov r0, r1, d17
+; SOFT-NEXT:    bx lr
+;
+; HARD-LABEL: test3:
+; HARD:       @ %bb.0: @ %entry
+; HARD-NEXT:    vmul.f64 d16, d0, d1
+; HARD-NEXT:    vmov.i32 d17, #0x80000000
+; HARD-NEXT:    vshl.i64 d0, d17, #32
+; HARD-NEXT:    vbsl d0, d2, d16
+; HARD-NEXT:    bx lr
+entry:
   %0 = fmul double %x, %y
   %1 = tail call double @copysign(double %0, double %z) nounwind readnone
   ret double %1
@@ -42,12 +72,34 @@ entry:
 
 ; rdar://9287902
 define float @test4() nounwind {
-entry:
 ; SOFT-LABEL: test4:
-; SOFT: vmov [[REG7:(d[0-9]+)]], r0, r1
-; SOFT: vmov.i32 [[REG6:(d[0-9]+)]], #0x80000000
-; SOFT: vshr.u64 [[REG7]], [[REG7]], #32
-; SOFT: vbsl [[REG6]], [[REG7]], 
+; SOFT:       @ %bb.0: @ %entry
+; SOFT-NEXT:    push {lr}
+; SOFT-NEXT:    bl _bar
+; SOFT-NEXT:    vmov d16, r0, r1
+; SOFT-NEXT:    vcvt.f32.f64 s0, d16
+; SOFT-NEXT:    vmov.i32 d17, #0x80000000
+; SOFT-NEXT:    vshr.u64 d16, d16, #32
+; SOFT-NEXT:    vmov.f32 d18, #5.000000e-01
+; SOFT-NEXT:    vbsl d17, d16, d18
+; SOFT-NEXT:    vadd.f32 d0, d0, d17
+; SOFT-NEXT:    vmov r0, s0
+; SOFT-NEXT:    pop {lr}
+;
+; HARD-LABEL: test4:
+; HARD:       @ %bb.0: @ %entry
+; HARD-NEXT:    .save {r11, lr}
+; HARD-NEXT:    push {r11, lr}
+; HARD-NEXT:    bl bar
+; HARD-NEXT:    vmov d16, r0, r1
+; HARD-NEXT:    vcvt.f32.f64 s0, d16
+; HARD-NEXT:    vmov.i32 d1, #0x80000000
+; HARD-NEXT:    vshr.u64 d16, d16, #32
+; HARD-NEXT:    vmov.f32 s4, #5.000000e-01
+; HARD-NEXT:    vbsl d1, d16, d2
+; HARD-NEXT:    vadd.f32 s0, s0, s2
+; HARD-NEXT:    pop {r11, pc}
+entry:
   %0 = tail call double (...) @bar() nounwind
   %1 = fptrunc double %0 to float
   %2 = tail call float @copysignf(float 5.000000e-01, float %1) nounwind readnone
diff --git a/llvm/test/CodeGen/ARM/fp16-promote.ll b/llvm/test/CodeGen/ARM/fp16-promote.ll
index 3cd07df671b99..11670d7b57ad8 100644
--- a/llvm/test/CodeGen/ARM/fp16-promote.ll
+++ b/llvm/test/CodeGen/ARM/fp16-promote.ll
@@ -424,7 +424,7 @@ declare half @llvm.fmuladd.f16(half %a, half %b, half %c) #0
 ; CHECK-FP16: vsqrt.f32
 ; CHECK-FP16: vcvtb.f16.f32
 ; CHECK-LIBCALL: bl __aeabi_h2f
-; CHECK-VFP-LIBCALL: vsqrt.f32
+; CHECK-LIBCALL-VFP: vsqrt.f32
 ; CHECK-NOVFP: bl sqrtf
 ; CHECK-LIBCALL: bl __aeabi_f2h
 define void @test_sqrt(half* %p) #0 {
@@ -700,18 +700,44 @@ define void @test_maximum(half* %p) #0 {
 }
 
 ; CHECK-FP16-LABEL: test_copysign:
-; CHECK-FP16: vcvtb.f32.f16
-; CHECK-FP16: vcvtb.f32.f16
-; CHECK-FP16: vbsl
-; CHECK-FP16: vcvtb.f16.f32
+; CHECK-FP16:         ldrh r2, [r0]
+; CHECK-FP16-NEXT:    vmov.i32 d0, #0x80000000
+; CHECK-FP16-NEXT:    ldrh r1, [r1]
+; CHECK-FP16-NEXT:    vmov s2, r2
+; CHECK-FP16-NEXT:    vmov s4, r1
+; CHECK-FP16-NEXT:    vcvtb.f32.f16 s2, s2
+; CHECK-FP16-NEXT:    vcvtb.f32.f16 s4, s4
+; CHECK-FP16-NEXT:    vbsl d0, d2, d1
+; CHECK-FP16-NEXT:    vcvtb.f16.f32 s0, s0
+; CHECK-FP16-NEXT:    vmov r1, s0
+; CHECK-FP16-NEXT:    strh r1, [r0]
+; CHECK-FP16-NEXT:    bx lr
+
 ; CHECK-LIBCALL-LABEL: test_copysign:
-; CHECK-LIBCALL: bl __aeabi_h2f
-; CHECK-LIBCALL: bl __aeabi_h2f
-; CHECK-VFP-LIBCALL: vbsl
+; CHECK-LIBCALL-VFP:         .fnstart
+; CHECK-LIBCALL-VFP-NEXT:    .save {r4, r5, r11, lr}
+; CHECK-LIBCALL-VFP-NEXT:    push {r4, r5, r11, lr}
+; CHECK-LIBCALL-VFP-NEXT:    .vsave {d8, d9}
+; CHECK-LIBCALL-VFP-NEXT:    vpush {d8, d9}
+; CHECK-LIBCALL-VFP-NEXT:    mov r5, r0
+; CHECK-LIBCALL-VFP-NEXT:    ldrh r0, [r0]
+; CHECK-LIBCALL-VFP-NEXT:    mov r4, r1
+; CHECK-LIBCALL: bl __aeabi_h2f
+; CHECK-LIBCALL-VFP:         ldrh r1, [r4]
+; CHECK-LIBCALL-VFP-NEXT:    vmov s18, r0
+; CHECK-LIBCALL-VFP-NEXT:    vmov.i32 d8, #0x80000000
+; CHECK-LIBCALL-VFP-NEXT:    mov r0, r1
+; CHECK-LIBCALL: bl __aeabi_h2f
+; CHECK-LIBCALL-VFP:         vmov s0, r0
+; CHECK-LIBCALL-VFP-NEXT:    vbsl d8, d0, d9
+; CHECK-LIBCALL-VFP-NEXT:    vmov r0, s16
+; CHECK-LIBCALL: bl __aeabi_f2h
+; CHECK-LIBCALL-VFP:         strh r0, [r5]
+; CHECK-LIBCALL-VFP-NEXT:    vpop {d8, d9}
+; CHECK-LIBCALL-VFP-NEXT:    pop {r4, r5, r11, pc}
 ; CHECK-NOVFP: and
 ; CHECK-NOVFP: bic
 ; CHECK-NOVFP: orr
-; CHECK-LIBCALL: bl __aeabi_f2h
 define void @test_copysign(half* %p, half* %q) #0 {
   %a = load half, half* %p, align 2
   %b = load half, half* %q, align 2
@@ -820,7 +846,7 @@ define void @test_round(half* %p) {
 ; CHECK-LIBCALL: bl __aeabi_h2f
 ; CHECK-LIBCALL: bl __aeabi_h2f
 ; CHECK-LIBCALL: bl __aeabi_h2f
-; CHECK-VFP-LIBCALL: vmla.f32
+; CHECK-LIBCALL-VFP: vmla.f32
 ; CHECK-NOVFP: bl __aeabi_fmul
 ; CHECK-LIBCALL: bl __aeabi_f2h
 define void @test_fmuladd(half* %p, half* %q, half* %r) #0 {
diff --git a/llvm/test/CodeGen/ARM/vbsl-constant.ll b/llvm/test/CodeGen/ARM/vbsl-constant.ll
index 6bcbbc8fa878d..83b34a133dd10 100644
--- a/llvm/test/CodeGen/ARM/vbsl-constant.ll
+++ b/llvm/test/CodeGen/ARM/vbsl-constant.ll
@@ -1,10 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=arm-apple-ios -mattr=+neon | FileCheck %s
 
 define <8 x i8> @v_bsli8(<8 x i8>* %A, <8 x i8>* %B, <8 x i8>* %C) nounwind {
-;CHECK-LABEL: v_bsli8:
-;CHECK: vldr
-;CHECK: vldr
-;CHECK: vbsl
+; CHECK-LABEL: v_bsli8:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vmov.i8 d16, #0x3
+; CHECK-NEXT:    vldr d17, [r2]
+; CHECK-NEXT:    vldr d18, [r0]
+; CHECK-NEXT:    vbsl d16, d18, d17
+; CHECK-NEXT:    vmov r0, r1, d16
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <8 x i8>, <8 x i8>* %A
 	%tmp2 = load <8 x i8>, <8 x i8>* %B
 	%tmp3 = load <8 x i8>, <8 x i8>* %C
@@ -15,10 +20,14 @@ define <8 x i8> @v_bsli8(<8 x i8>* %A, <8 x i8>* %B, <8 x i8>* %C) nounwind {
 }
 
 define <4 x i16> @v_bsli16(<4 x i16>* %A, <4 x i16>* %B, <4 x i16>* %C) nounwind {
-;CHECK-LABEL: v_bsli16:
-;CHECK: vldr
-;CHECK: vldr
-;CHECK: vbsl
+; CHECK-LABEL: v_bsli16:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vmov.i16 d16, #0x3
+; CHECK-NEXT:    vldr d17, [r2]
+; CHECK-NEXT:    vldr d18, [r0]
+; CHECK-NEXT:    vbsl d16, d18, d17
+; CHECK-NEXT:    vmov r0, r1, d16
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <4 x i16>, <4 x i16>* %A
 	%tmp2 = load <4 x i16>, <4 x i16>* %B
 	%tmp3 = load <4 x i16>, <4 x i16>* %C
@@ -29,10 +38,14 @@ define <4 x i16> @v_bsli16(<4 x i16>* %A, <4 x i16>* %B, <4 x i16>* %C) nounwind
 }
 
 define <2 x i32> @v_bsli32(<2 x i32>* %A, <2 x i32>* %B, <2 x i32>* %C) nounwind {
-;CHECK-LABEL: v_bsli32:
-;CHECK: vldr
-;CHECK: vldr
-;CHECK: vbsl
+; CHECK-LABEL: v_bsli32:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vmov.i32 d16, #0x3
+; CHECK-NEXT:    vldr d17, [r2]
+; CHECK-NEXT:    vldr d18, [r0]
+; CHECK-NEXT:    vbsl d16, d18, d17
+; CHECK-NEXT:    vmov r0, r1, d16
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <2 x i32>, <2 x i32>* %A
 	%tmp2 = load <2 x i32>, <2 x i32>* %B
 	%tmp3 = load <2 x i32>, <2 x i32>* %C
@@ -43,11 +56,14 @@ define <2 x i32> @v_bsli32(<2 x i32>* %A, <2 x i32>* %B, <2 x i32>* %C) nounwind
 }
 
 define <1 x i64> @v_bsli64(<1 x i64>* %A, <1 x i64>* %B, <1 x i64>* %C) nounwind {
-;CHECK-LABEL: v_bsli64:
-;CHECK: vldr
-;CHECK: vldr
-;CHECK: vldr
-;CHECK: vbsl
+; CHECK-LABEL: v_bsli64:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d17, [r2]
+; CHECK-NEXT:    vldr d16, LCPI3_0
+; CHECK-NEXT:    vldr d18, [r0]
+; CHECK-NEXT:    vbsl d16, d18, d17
+; CHECK-NEXT:    vmov r0, r1, d16
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <1 x i64>, <1 x i64>* %A
 	%tmp2 = load <1 x i64>, <1 x i64>* %B
 	%tmp3 = load <1 x i64>, <1 x i64>* %C
@@ -58,10 +74,15 @@ define <1 x i64> @v_bsli64(<1 x i64>* %A, <1 x i64>* %B, <1 x i64>* %C) nounwind
 }
 
 define <16 x i8> @v_bslQi8(<16 x i8>* %A, <16 x i8>* %B, <16 x i8>* %C) nounwind {
-;CHECK-LABEL: v_bslQi8:
-;CHECK: vld1.32
-;CHECK: vld1.32
-;CHECK: vbsl
+; CHECK-LABEL: v_bslQi8:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vld1.32 {d16, d17}, [r2]
+; CHECK-NEXT:    vmov.i8 q9, #0x3
+; CHECK-NEXT:    vld1.32 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <16 x i8>, <16 x i8>* %A
 	%tmp2 = load <16 x i8>, <16 x i8>* %B
 	%tmp3 = load <16 x i8>, <16 x i8>* %C
@@ -72,10 +93,15 @@ define <16 x i8> @v_bslQi8(<16 x i8>* %A, <16 x i8>* %B, <16 x i8>* %C) nounwind
 }
 
 define <8 x i16> @v_bslQi16(<8 x i16>* %A, <8 x i16>* %B, <8 x i16>* %C) nounwind {
-;CHECK-LABEL: v_bslQi16:
-;CHECK: vld1.32
-;CHECK: vld1.32
-;CHECK: vbsl
+; CHECK-LABEL: v_bslQi16:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vld1.32 {d16, d17}, [r2]
+; CHECK-NEXT:    vmov.i16 q9, #0x3
+; CHECK-NEXT:    vld1.32 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <8 x i16>, <8 x i16>* %A
 	%tmp2 = load <8 x i16>, <8 x i16>* %B
 	%tmp3 = load <8 x i16>, <8 x i16>* %C
@@ -86,10 +112,15 @@ define <8 x i16> @v_bslQi16(<8 x i16>* %A, <8 x i16>* %B, <8 x i16>* %C) nounwin
 }
 
 define <4 x i32> @v_bslQi32(<4 x i32>* %A, <4 x i32>* %B, <4 x i32>* %C) nounwind {
-;CHECK-LABEL: v_bslQi32:
-;CHECK: vld1.32
-;CHECK: vld1.32
-;CHECK: vbsl
+; CHECK-LABEL: v_bslQi32:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vld1.32 {d16, d17}, [r2]
+; CHECK-NEXT:    vmov.i32 q9, #0x3
+; CHECK-NEXT:    vld1.32 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <4 x i32>, <4 x i32>* %A
 	%tmp2 = load <4 x i32>, <4 x i32>* %B
 	%tmp3 = load <4 x i32>, <4 x i32>* %C
@@ -100,11 +131,16 @@ define <4 x i32> @v_bslQi32(<4 x i32>* %A, <4 x i32>* %B, <4 x i32>* %C) nounwin
 }
 
 define <2 x i64> @v_bslQi64(<2 x i64>* %A, <2 x i64>* %B, <2 x i64>* %C) nounwind {
-;CHECK-LABEL: v_bslQi64:
-;CHECK: vld1.32
-;CHECK: vld1.32
-;CHECK: vld1.64
-;CHECK: vbsl
+; CHECK-LABEL: v_bslQi64:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vld1.32 {d16, d17}, [r2]
+; CHECK-NEXT:    vld1.32 {d18, d19}, [r0]
+; CHECK-NEXT:    adr r0, LCPI7_0
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0:128]
+; CHECK-NEXT:    vbsl q10, q9, q8
+; CHECK-NEXT:    vmov r0, r1, d20
+; CHECK-NEXT:    vmov r2, r3, d21
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <2 x i64>, <2 x i64>* %A
 	%tmp2 = load <2 x i64>, <2 x i64>* %B
 	%tmp3 = load <2 x i64>, <2 x i64>* %C
diff --git a/llvm/test/CodeGen/ARM/vbsl.ll b/llvm/test/CodeGen/ARM/vbsl.ll
index 6812dd90a1004..01e1ffb2e983a 100644
--- a/llvm/test/CodeGen/ARM/vbsl.ll
+++ b/llvm/test/CodeGen/ARM/vbsl.ll
@@ -1,10 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=arm-eabi -mattr=+neon %s -o - | FileCheck %s
 
 ; rdar://12471808
 
 define <8 x i8> @v_bsli8(<8 x i8>* %A, <8 x i8>* %B, <8 x i8>* %C) nounwind {
-;CHECK-LABEL: v_bsli8:
-;CHECK: vbsl
+; CHECK-LABEL: v_bsli8:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [r2]
+; CHECK-NEXT:    vldr d17, [r1]
+; CHECK-NEXT:    vldr d18, [r0]
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <8 x i8>, <8 x i8>* %A
 	%tmp2 = load <8 x i8>, <8 x i8>* %B
 	%tmp3 = load <8 x i8>, <8 x i8>* %C
@@ -16,8 +23,14 @@ define <8 x i8> @v_bsli8(<8 x i8>* %A, <8 x i8>* %B, <8 x i8>* %C) nounwind {
 }
 
 define <4 x i16> @v_bsli16(<4 x i16>* %A, <4 x i16>* %B, <4 x i16>* %C) nounwind {
-;CHECK-LABEL: v_bsli16:
-;CHECK: vbsl
+; CHECK-LABEL: v_bsli16:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [r2]
+; CHECK-NEXT:    vldr d17, [r1]
+; CHECK-NEXT:    vldr d18, [r0]
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <4 x i16>, <4 x i16>* %A
 	%tmp2 = load <4 x i16>, <4 x i16>* %B
 	%tmp3 = load <4 x i16>, <4 x i16>* %C
@@ -29,8 +42,14 @@ define <4 x i16> @v_bsli16(<4 x i16>* %A, <4 x i16>* %B, <4 x i16>* %C) nounwind
 }
 
 define <2 x i32> @v_bsli32(<2 x i32>* %A, <2 x i32>* %B, <2 x i32>* %C) nounwind {
-;CHECK-LABEL: v_bsli32:
-;CHECK: vbsl
+; CHECK-LABEL: v_bsli32:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [r2]
+; CHECK-NEXT:    vldr d17, [r1]
+; CHECK-NEXT:    vldr d18, [r0]
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <2 x i32>, <2 x i32>* %A
 	%tmp2 = load <2 x i32>, <2 x i32>* %B
 	%tmp3 = load <2 x i32>, <2 x i32>* %C
@@ -42,8 +61,14 @@ define <2 x i32> @v_bsli32(<2 x i32>* %A, <2 x i32>* %B, <2 x i32>* %C) nounwind
 }
 
 define <1 x i64> @v_bsli64(<1 x i64>* %A, <1 x i64>* %B, <1 x i64>* %C) nounwind {
-;CHECK-LABEL: v_bsli64:
-;CHECK: vbsl
+; CHECK-LABEL: v_bsli64:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [r2]
+; CHECK-NEXT:    vldr d17, [r1]
+; CHECK-NEXT:    vldr d18, [r0]
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <1 x i64>, <1 x i64>* %A
 	%tmp2 = load <1 x i64>, <1 x i64>* %B
 	%tmp3 = load <1 x i64>, <1 x i64>* %C
@@ -55,8 +80,15 @@ define <1 x i64> @v_bsli64(<1 x i64>* %A, <1 x i64>* %B, <1 x i64>* %C) nounwind
 }
 
 define <16 x i8> @v_bslQi8(<16 x i8>* %A, <16 x i8>* %B, <16 x i8>* %C) nounwind {
-;CHECK-LABEL: v_bslQi8:
-;CHECK: vbsl
+; CHECK-LABEL: v_bslQi8:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r2]
+; CHECK-NEXT:    vld1.64 {d18, d19}, [r1]
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q10, q9, q8
+; CHECK-NEXT:    vmov r0, r1, d20
+; CHECK-NEXT:    vmov r2, r3, d21
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <16 x i8>, <16 x i8>* %A
 	%tmp2 = load <16 x i8>, <16 x i8>* %B
 	%tmp3 = load <16 x i8>, <16 x i8>* %C
@@ -68,8 +100,15 @@ define <16 x i8> @v_bslQi8(<16 x i8>* %A, <16 x i8>* %B, <16 x i8>* %C) nounwind
 }
 
 define <8 x i16> @v_bslQi16(<8 x i16>* %A, <8 x i16>* %B, <8 x i16>* %C) nounwind {
-;CHECK-LABEL: v_bslQi16:
-;CHECK: vbsl
+; CHECK-LABEL: v_bslQi16:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r2]
+; CHECK-NEXT:    vld1.64 {d18, d19}, [r1]
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q10, q9, q8
+; CHECK-NEXT:    vmov r0, r1, d20
+; CHECK-NEXT:    vmov r2, r3, d21
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <8 x i16>, <8 x i16>* %A
 	%tmp2 = load <8 x i16>, <8 x i16>* %B
 	%tmp3 = load <8 x i16>, <8 x i16>* %C
@@ -81,8 +120,15 @@ define <8 x i16> @v_bslQi16(<8 x i16>* %A, <8 x i16>* %B, <8 x i16>* %C) nounwin
 }
 
 define <4 x i32> @v_bslQi32(<4 x i32>* %A, <4 x i32>* %B, <4 x i32>* %C) nounwind {
-;CHECK-LABEL: v_bslQi32:
-;CHECK: vbsl
+; CHECK-LABEL: v_bslQi32:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r2]
+; CHECK-NEXT:    vld1.64 {d18, d19}, [r1]
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q10, q9, q8
+; CHECK-NEXT:    vmov r0, r1, d20
+; CHECK-NEXT:    vmov r2, r3, d21
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <4 x i32>, <4 x i32>* %A
 	%tmp2 = load <4 x i32>, <4 x i32>* %B
 	%tmp3 = load <4 x i32>, <4 x i32>* %C
@@ -94,8 +140,15 @@ define <4 x i32> @v_bslQi32(<4 x i32>* %A, <4 x i32>* %B, <4 x i32>* %C) nounwin
 }
 
 define <2 x i64> @v_bslQi64(<2 x i64>* %A, <2 x i64>* %B, <2 x i64>* %C) nounwind {
-;CHECK-LABEL: v_bslQi64:
-;CHECK: vbsl
+; CHECK-LABEL: v_bslQi64:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r2]
+; CHECK-NEXT:    vld1.64 {d18, d19}, [r1]
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q10, q9, q8
+; CHECK-NEXT:    vmov r0, r1, d20
+; CHECK-NEXT:    vmov r2, r3, d21
+; CHECK-NEXT:    mov pc, lr
 	%tmp1 = load <2 x i64>, <2 x i64>* %A
 	%tmp2 = load <2 x i64>, <2 x i64>* %B
 	%tmp3 = load <2 x i64>, <2 x i64>* %C
@@ -108,84 +161,180 @@ define <2 x i64> @v_bslQi64(<2 x i64>* %A, <2 x i64>* %B, <2 x i64>* %C) nounwin
 
 define <8 x i8> @f1(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: f1:
-; CHECK: vbsl
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [sp]
+; CHECK-NEXT:    vmov d17, r2, r3
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
   %vbsl.i = tail call <8 x i8> @llvm.arm.neon.vbsl.v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c) nounwind
   ret <8 x i8> %vbsl.i
 }
 
 define <4 x i16> @f2(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: f2:
-; CHECK: vbsl
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [sp]
+; CHECK-NEXT:    vmov d17, r2, r3
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
   %vbsl3.i = tail call <4 x i16> @llvm.arm.neon.vbsl.v4i16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c) nounwind
   ret <4 x i16> %vbsl3.i
 }
 
 define <2 x i32> @f3(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: f3:
-; CHECK: vbsl
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [sp]
+; CHECK-NEXT:    vmov d17, r2, r3
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
   %vbsl3.i = tail call <2 x i32> @llvm.arm.neon.vbsl.v2i32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) nounwind
   ret <2 x i32> %vbsl3.i
 }
 
 define <2 x float> @f4(<2 x float> %a, <2 x float> %b, <2 x float> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: f4:
-; CHECK: vbsl
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [sp]
+; CHECK-NEXT:    vmov d17, r2, r3
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
   %vbsl4.i = tail call <2 x float> @llvm.arm.neon.vbsl.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c) nounwind
   ret <2 x float> %vbsl4.i
 }
 
 define <16 x i8> @g1(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: g1:
-; CHECK: vbsl
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    add r12, sp, #16
+; CHECK-NEXT:    vmov d19, r2, r3
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r12]
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    mov r0, sp
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
   %vbsl.i = tail call <16 x i8> @llvm.arm.neon.vbsl.v16i8(<16 x i8> %a, <16 x i8> %b, <16 x i8> %c) nounwind
   ret <16 x i8> %vbsl.i
 }
 
 define <8 x i16> @g2(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: g2:
-; CHECK: vbsl
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    add r12, sp, #16
+; CHECK-NEXT:    vmov d19, r2, r3
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r12]
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    mov r0, sp
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
   %vbsl3.i = tail call <8 x i16> @llvm.arm.neon.vbsl.v8i16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c) nounwind
   ret <8 x i16> %vbsl3.i
 }
 
 define <4 x i32> @g3(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: g3:
-; CHECK: vbsl
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    add r12, sp, #16
+; CHECK-NEXT:    vmov d19, r2, r3
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r12]
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    mov r0, sp
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
   %vbsl3.i = tail call <4 x i32> @llvm.arm.neon.vbsl.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) nounwind
   ret <4 x i32> %vbsl3.i
 }
 
 define <4 x float> @g4(<4 x float> %a, <4 x float> %b, <4 x float> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: g4:
-; CHECK: vbsl
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    add r12, sp, #16
+; CHECK-NEXT:    vmov d19, r2, r3
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r12]
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    mov r0, sp
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
   %vbsl4.i = tail call <4 x float> @llvm.arm.neon.vbsl.v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c) nounwind
   ret <4 x float> %vbsl4.i
 }
 
 define <1 x i64> @test_vbsl_s64(<1 x i64> %a, <1 x i64> %b, <1 x i64> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: test_vbsl_s64:
-; CHECK: vbsl d
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [sp]
+; CHECK-NEXT:    vmov d17, r2, r3
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
   %vbsl3.i = tail call <1 x i64> @llvm.arm.neon.vbsl.v1i64(<1 x i64> %a, <1 x i64> %b, <1 x i64> %c) nounwind
   ret <1 x i64> %vbsl3.i
 }
 
 define <1 x i64> @test_vbsl_u64(<1 x i64> %a, <1 x i64> %b, <1 x i64> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: test_vbsl_u64:
-; CHECK: vbsl d
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    vldr d16, [sp]
+; CHECK-NEXT:    vmov d17, r2, r3
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    vbsl d18, d17, d16
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    mov pc, lr
   %vbsl3.i = tail call <1 x i64> @llvm.arm.neon.vbsl.v1i64(<1 x i64> %a, <1 x i64> %b, <1 x i64> %c) nounwind
   ret <1 x i64> %vbsl3.i
 }
 
 define <2 x i64> @test_vbslq_s64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: test_vbslq_s64:
-; CHECK: vbsl q
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    add r12, sp, #16
+; CHECK-NEXT:    vmov d19, r2, r3
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r12]
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    mov r0, sp
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
   %vbsl3.i = tail call <2 x i64> @llvm.arm.neon.vbsl.v2i64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) nounwind
   ret <2 x i64> %vbsl3.i
 }
 
 define <2 x i64> @test_vbslq_u64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) nounwind readnone optsize ssp {
 ; CHECK-LABEL: test_vbslq_u64:
-; CHECK: vbsl q
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    add r12, sp, #16
+; CHECK-NEXT:    vmov d19, r2, r3
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r12]
+; CHECK-NEXT:    vmov d18, r0, r1
+; CHECK-NEXT:    mov r0, sp
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0]
+; CHECK-NEXT:    vbsl q9, q10, q8
+; CHECK-NEXT:    vmov r0, r1, d18
+; CHECK-NEXT:    vmov r2, r3, d19
+; CHECK-NEXT:    mov pc, lr
   %vbsl3.i = tail call <2 x i64> @llvm.arm.neon.vbsl.v2i64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) nounwind
   ret <2 x i64> %vbsl3.i
 }
diff --git a/llvm/test/CodeGen/ARM/vselect_imax.ll b/llvm/test/CodeGen/ARM/vselect_imax.ll
index e212b37fa1f5f..f9d88cc4af982 100644
--- a/llvm/test/CodeGen/ARM/vselect_imax.ll
+++ b/llvm/test/CodeGen/ARM/vselect_imax.ll
@@ -63,11 +63,66 @@ define void @func_blend15(%T0_15* %loadaddr, %T0_15* %loadaddr2,
 ; lowering we also need to adjust the cost.
 %T0_18 = type <4 x i64>
 %T1_18 = type <4 x i1>
-; CHECK-LABEL: func_blend18:
 define void @func_blend18(%T0_18* %loadaddr, %T0_18* %loadaddr2,
                            %T1_18* %blend, %T0_18* %storeaddr) {
-; CHECK: vbsl
-; CHECK: vbsl
+; CHECK-LABEL: func_blend18:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r4, r5, r6, r7, r11, lr}
+; CHECK-NEXT:    push {r4, r5, r6, r7, r11, lr}
+; CHECK-NEXT:    vld1.64 {d22, d23}, [r0:128]!
+; CHECK-NEXT:    vld1.64 {d18, d19}, [r1:128]!
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r1:128]
+; CHECK-NEXT:    mov r1, #0
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r0:128]
+; CHECK-NEXT:    vmov.32 r12, d16[0]
+; CHECK-NEXT:    vmov.32 r2, d20[0]
+; CHECK-NEXT:    vmov.32 lr, d16[1]
+; CHECK-NEXT:    vmov.32 r0, d20[1]
+; CHECK-NEXT:    vmov.32 r7, d18[0]
+; CHECK-NEXT:    vmov.32 r5, d22[0]
+; CHECK-NEXT:    vmov.32 r4, d22[1]
+; CHECK-NEXT:    vmov.32 r6, d17[0]
+; CHECK-NEXT:    subs r2, r2, r12
+; CHECK-NEXT:    vmov.32 r2, d18[1]
+; CHECK-NEXT:    sbcs r0, r0, lr
+; CHECK-NEXT:    mov r0, #0
+; CHECK-NEXT:    movlt r0, #1
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    mvnne r0, #0
+; CHECK-NEXT:    subs r7, r5, r7
+; CHECK-NEXT:    vmov.32 r7, d21[0]
+; CHECK-NEXT:    vmov.32 r5, d17[1]
+; CHECK-NEXT:    sbcs r2, r4, r2
+; CHECK-NEXT:    vmov.32 r4, d21[1]
+; CHECK-NEXT:    mov r2, #0
+; CHECK-NEXT:    movlt r2, #1
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    mvnne r2, #0
+; CHECK-NEXT:    subs r7, r7, r6
+; CHECK-NEXT:    vmov.32 r6, d23[0]
+; CHECK-NEXT:    vmov.32 r7, d19[0]
+; CHECK-NEXT:    sbcs r5, r4, r5
+; CHECK-NEXT:    mov r4, #0
+; CHECK-NEXT:    movlt r4, #1
+; CHECK-NEXT:    vmov.32 r5, d19[1]
+; CHECK-NEXT:    subs r7, r6, r7
+; CHECK-NEXT:    vmov.32 r7, d23[1]
+; CHECK-NEXT:    sbcs r7, r7, r5
+; CHECK-NEXT:    movlt r1, #1
+; CHECK-NEXT:    cmp r1, #0
+; CHECK-NEXT:    mvnne r1, #0
+; CHECK-NEXT:    cmp r4, #0
+; CHECK-NEXT:    vdup.32 d25, r1
+; CHECK-NEXT:    mvnne r4, #0
+; CHECK-NEXT:    vdup.32 d24, r2
+; CHECK-NEXT:    vdup.32 d27, r4
+; CHECK-NEXT:    vbsl q12, q11, q9
+; CHECK-NEXT:    vdup.32 d26, r0
+; CHECK-NEXT:    vbsl q13, q10, q8
+; CHECK-NEXT:    vst1.64 {d24, d25}, [r3:128]!
+; CHECK-NEXT:    vst1.64 {d26, d27}, [r3:128]
+; CHECK-NEXT:    pop {r4, r5, r6, r7, r11, lr}
+; CHECK-NEXT:    mov pc, lr
   %v0 = load %T0_18, %T0_18* %loadaddr
   %v1 = load %T0_18, %T0_18* %loadaddr2
   %c = icmp slt %T0_18 %v0, %v1
@@ -79,13 +134,126 @@ define void @func_blend18(%T0_18* %loadaddr, %T0_18* %loadaddr2,
 }
 %T0_19 = type <8 x i64>
 %T1_19 = type <8 x i1>
-; CHECK-LABEL: func_blend19:
 define void @func_blend19(%T0_19* %loadaddr, %T0_19* %loadaddr2,
                            %T1_19* %blend, %T0_19* %storeaddr) {
-; CHECK: vbsl
-; CHECK: vbsl
-; CHECK: vbsl
-; CHECK: vbsl
+; CHECK-LABEL: func_blend19:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r4, r5, r6, lr}
+; CHECK-NEXT:    push {r4, r5, r6, lr}
+; CHECK-NEXT:    mov r12, r1
+; CHECK-NEXT:    mov r2, r0
+; CHECK-NEXT:    vld1.64 {d24, d25}, [r12:128]!
+; CHECK-NEXT:    mov r6, #0
+; CHECK-NEXT:    mov lr, #0
+; CHECK-NEXT:    vld1.64 {d28, d29}, [r2:128]!
+; CHECK-NEXT:    vld1.64 {d16, d17}, [r12:128]
+; CHECK-NEXT:    vld1.64 {d18, d19}, [r2:128]
+; CHECK-NEXT:    add r2, r1, #32
+; CHECK-NEXT:    add r1, r1, #48
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r2:128]
+; CHECK-NEXT:    add r2, r0, #32
+; CHECK-NEXT:    add r0, r0, #48
+; CHECK-NEXT:    vld1.64 {d30, d31}, [r2:128]
+; CHECK-NEXT:    vmov.32 r4, d16[0]
+; CHECK-NEXT:    vmov.32 r2, d18[0]
+; CHECK-NEXT:    vmov.32 r12, d16[1]
+; CHECK-NEXT:    vmov.32 r5, d18[1]
+; CHECK-NEXT:    vld1.64 {d22, d23}, [r1:128]
+; CHECK-NEXT:    vmov.32 r1, d21[0]
+; CHECK-NEXT:    vld1.64 {d26, d27}, [r0:128]
+; CHECK-NEXT:    vmov.32 r0, d21[1]
+; CHECK-NEXT:    subs r2, r2, r4
+; CHECK-NEXT:    vmov.32 r4, d31[1]
+; CHECK-NEXT:    vmov.32 r2, d31[0]
+; CHECK-NEXT:    sbcs r5, r5, r12
+; CHECK-NEXT:    mov r12, #0
+; CHECK-NEXT:    movlt r12, #1
+; CHECK-NEXT:    cmp r12, #0
+; CHECK-NEXT:    mvnne r12, #0
+; CHECK-NEXT:    vmov.32 r5, d25[0]
+; CHECK-NEXT:    subs r1, r2, r1
+; CHECK-NEXT:    mov r2, #0
+; CHECK-NEXT:    sbcs r0, r4, r0
+; CHECK-NEXT:    vmov.32 r1, d29[0]
+; CHECK-NEXT:    vmov.32 r0, d25[1]
+; CHECK-NEXT:    movlt r2, #1
+; CHECK-NEXT:    vmov.32 r4, d29[1]
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    mvnne r2, #0
+; CHECK-NEXT:    vdup.32 d5, r2
+; CHECK-NEXT:    subs r1, r1, r5
+; CHECK-NEXT:    vmov.32 r5, d24[1]
+; CHECK-NEXT:    vmov.32 r1, d24[0]
+; CHECK-NEXT:    sbcs r0, r4, r0
+; CHECK-NEXT:    vmov.32 r4, d28[0]
+; CHECK-NEXT:    mov r0, #0
+; CHECK-NEXT:    movlt r0, #1
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    mvnne r0, #0
+; CHECK-NEXT:    vdup.32 d1, r0
+; CHECK-NEXT:    vmov.32 r0, d19[0]
+; CHECK-NEXT:    subs r1, r4, r1
+; CHECK-NEXT:    vmov.32 r4, d17[0]
+; CHECK-NEXT:    vmov.32 r1, d28[1]
+; CHECK-NEXT:    sbcs r1, r1, r5
+; CHECK-NEXT:    vmov.32 r5, d17[1]
+; CHECK-NEXT:    mov r1, #0
+; CHECK-NEXT:    movlt r1, #1
+; CHECK-NEXT:    cmp r1, #0
+; CHECK-NEXT:    mvnne r1, #0
+; CHECK-NEXT:    subs r0, r0, r4
+; CHECK-NEXT:    vmov.32 r0, d19[1]
+; CHECK-NEXT:    vmov.32 r4, d22[0]
+; CHECK-NEXT:    vdup.32 d0, r1
+; CHECK-NEXT:    vmov.32 r1, d22[1]
+; CHECK-NEXT:    vbsl q0, q14, q12
+; CHECK-NEXT:    sbcs r0, r0, r5
+; CHECK-NEXT:    vmov.32 r5, d26[0]
+; CHECK-NEXT:    mov r0, #0
+; CHECK-NEXT:    movlt r0, #1
+; CHECK-NEXT:    subs r4, r5, r4
+; CHECK-NEXT:    vmov.32 r5, d20[0]
+; CHECK-NEXT:    vmov.32 r4, d26[1]
+; CHECK-NEXT:    sbcs r1, r4, r1
+; CHECK-NEXT:    vmov.32 r4, d30[0]
+; CHECK-NEXT:    mov r1, #0
+; CHECK-NEXT:    movlt r1, #1
+; CHECK-NEXT:    subs r4, r4, r5
+; CHECK-NEXT:    vmov.32 r5, d30[1]
+; CHECK-NEXT:    vmov.32 r4, d20[1]
+; CHECK-NEXT:    sbcs r4, r5, r4
+; CHECK-NEXT:    vmov.32 r5, d27[0]
+; CHECK-NEXT:    vmov.32 r4, d23[0]
+; CHECK-NEXT:    movlt r6, #1
+; CHECK-NEXT:    subs r4, r5, r4
+; CHECK-NEXT:    vmov.32 r5, d27[1]
+; CHECK-NEXT:    vmov.32 r4, d23[1]
+; CHECK-NEXT:    sbcs r4, r5, r4
+; CHECK-NEXT:    movlt lr, #1
+; CHECK-NEXT:    cmp lr, #0
+; CHECK-NEXT:    mvnne lr, #0
+; CHECK-NEXT:    cmp r6, #0
+; CHECK-NEXT:    mvnne r6, #0
+; CHECK-NEXT:    cmp r1, #0
+; CHECK-NEXT:    mvnne r1, #0
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    vdup.32 d4, r6
+; CHECK-NEXT:    mvnne r0, #0
+; CHECK-NEXT:    vdup.32 d3, lr
+; CHECK-NEXT:    vbsl q2, q15, q10
+; CHECK-NEXT:    vdup.32 d21, r0
+; CHECK-NEXT:    add r0, r3, #32
+; CHECK-NEXT:    vdup.32 d2, r1
+; CHECK-NEXT:    vdup.32 d20, r12
+; CHECK-NEXT:    vbsl q1, q13, q11
+; CHECK-NEXT:    vst1.64 {d4, d5}, [r0:128]
+; CHECK-NEXT:    add r0, r3, #48
+; CHECK-NEXT:    vbsl q10, q9, q8
+; CHECK-NEXT:    vst1.64 {d0, d1}, [r3:128]!
+; CHECK-NEXT:    vst1.64 {d2, d3}, [r0:128]
+; CHECK-NEXT:    vst1.64 {d20, d21}, [r3:128]
+; CHECK-NEXT:    pop {r4, r5, r6, lr}
+; CHECK-NEXT:    mov pc, lr
   %v0 = load %T0_19, %T0_19* %loadaddr
   %v1 = load %T0_19, %T0_19* %loadaddr2
   %c = icmp slt %T0_19 %v0, %v1
@@ -97,17 +265,249 @@ define void @func_blend19(%T0_19* %loadaddr, %T0_19* %loadaddr2,
 }
 %T0_20 = type <16 x i64>
 %T1_20 = type <16 x i1>
-; CHECK-LABEL: func_blend20:
 define void @func_blend20(%T0_20* %loadaddr, %T0_20* %loadaddr2,
                            %T1_20* %blend, %T0_20* %storeaddr) {
-; CHECK: vbsl
-; CHECK: vbsl
-; CHECK: vbsl
-; CHECK: vbsl
-; CHECK: vbsl
-; CHECK: vbsl
-; CHECK: vbsl
-; CHECK: vbsl
+; CHECK-LABEL: func_blend20:
+; CHECK:       @ %bb.0:
+; CHECK-NEXT:    .save {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+; CHECK-NEXT:    push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+; CHECK-NEXT:    .pad #4
+; CHECK-NEXT:    sub sp, sp, #4
+; CHECK-NEXT:    .vsave {d8, d9, d10, d11}
+; CHECK-NEXT:    vpush {d8, d9, d10, d11}
+; CHECK-NEXT:    .pad #8
+; CHECK-NEXT:    sub sp, sp, #8
+; CHECK-NEXT:    add r9, r1, #64
+; CHECK-NEXT:    mov r2, #32
+; CHECK-NEXT:    add r8, r0, #64
+; CHECK-NEXT:    vld1.64 {d18, d19}, [r9:128], r2
+; CHECK-NEXT:    mov r10, #0
+; CHECK-NEXT:    vld1.64 {d22, d23}, [r8:128], r2
+; CHECK-NEXT:    vmov.32 r2, d19[0]
+; CHECK-NEXT:    str r3, [sp, #4] @ 4-byte Spill
+; CHECK-NEXT:    vmov.32 r7, d23[0]
+; CHECK-NEXT:    mov r3, #0
+; CHECK-NEXT:    vmov.32 r5, d19[1]
+; CHECK-NEXT:    vmov.32 r6, d23[1]
+; CHECK-NEXT:    vld1.64 {d2, d3}, [r9:128]!
+; CHECK-NEXT:    vmov.32 r12, d2[0]
+; CHECK-NEXT:    subs r2, r7, r2
+; CHECK-NEXT:    mov r7, r1
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r7:128]!
+; CHECK-NEXT:    sbcs r2, r6, r5
+; CHECK-NEXT:    vmov.32 r5, d18[0]
+; CHECK-NEXT:    mov r2, #0
+; CHECK-NEXT:    vmov.32 r6, d22[0]
+; CHECK-NEXT:    movlt r2, #1
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    vld1.64 {d0, d1}, [r7:128]
+; CHECK-NEXT:    mvnne r2, #0
+; CHECK-NEXT:    vdup.32 d17, r2
+; CHECK-NEXT:    mov r2, r0
+; CHECK-NEXT:    subs r5, r6, r5
+; CHECK-NEXT:    vmov.32 r6, d22[1]
+; CHECK-NEXT:    vmov.32 r5, d18[1]
+; CHECK-NEXT:    sbcs r5, r6, r5
+; CHECK-NEXT:    mov r5, #0
+; CHECK-NEXT:    movlt r5, #1
+; CHECK-NEXT:    cmp r5, #0
+; CHECK-NEXT:    mvnne r5, #0
+; CHECK-NEXT:    vdup.32 d16, r5
+; CHECK-NEXT:    vbsl q8, q11, q9
+; CHECK-NEXT:    vld1.64 {d22, d23}, [r2:128]!
+; CHECK-NEXT:    vmov.32 r5, d21[0]
+; CHECK-NEXT:    vmov.32 r6, d23[0]
+; CHECK-NEXT:    vld1.64 {d30, d31}, [r2:128]
+; CHECK-NEXT:    vmov.32 r2, d1[0]
+; CHECK-NEXT:    vmov.32 r7, d30[0]
+; CHECK-NEXT:    subs r5, r6, r5
+; CHECK-NEXT:    vmov.32 r6, d23[1]
+; CHECK-NEXT:    vmov.32 r5, d21[1]
+; CHECK-NEXT:    sbcs r5, r6, r5
+; CHECK-NEXT:    vmov.32 r6, d22[0]
+; CHECK-NEXT:    mov r5, #0
+; CHECK-NEXT:    movlt r5, #1
+; CHECK-NEXT:    cmp r5, #0
+; CHECK-NEXT:    mvnne r5, #0
+; CHECK-NEXT:    vdup.32 d19, r5
+; CHECK-NEXT:    vmov.32 r5, d20[0]
+; CHECK-NEXT:    subs r5, r6, r5
+; CHECK-NEXT:    vmov.32 r6, d22[1]
+; CHECK-NEXT:    vmov.32 r5, d20[1]
+; CHECK-NEXT:    sbcs r5, r6, r5
+; CHECK-NEXT:    mov r5, #0
+; CHECK-NEXT:    movlt r5, #1
+; CHECK-NEXT:    cmp r5, #0
+; CHECK-NEXT:    mvnne r5, #0
+; CHECK-NEXT:    vdup.32 d18, r5
+; CHECK-NEXT:    add r5, r0, #32
+; CHECK-NEXT:    vbsl q9, q11, q10
+; CHECK-NEXT:    vld1.64 {d22, d23}, [r5:128]
+; CHECK-NEXT:    add r5, r1, #32
+; CHECK-NEXT:    vld1.64 {d24, d25}, [r5:128]
+; CHECK-NEXT:    vmov.32 r5, d24[0]
+; CHECK-NEXT:    vmov.32 r6, d22[0]
+; CHECK-NEXT:    vmov.32 r4, d23[0]
+; CHECK-NEXT:    vld1.64 {d20, d21}, [r8:128]!
+; CHECK-NEXT:    vmov.32 r11, d21[0]
+; CHECK-NEXT:    subs r5, r6, r5
+; CHECK-NEXT:    vmov.32 r6, d22[1]
+; CHECK-NEXT:    vmov.32 r5, d24[1]
+; CHECK-NEXT:    sbcs r5, r6, r5
+; CHECK-NEXT:    vmov.32 r6, d25[0]
+; CHECK-NEXT:    movlt r10, #1
+; CHECK-NEXT:    cmp r10, #0
+; CHECK-NEXT:    mvnne r10, #0
+; CHECK-NEXT:    subs r4, r4, r6
+; CHECK-NEXT:    vmov.32 r6, d23[1]
+; CHECK-NEXT:    vmov.32 r4, d25[1]
+; CHECK-NEXT:    sbcs r4, r6, r4
+; CHECK-NEXT:    mov r6, #0
+; CHECK-NEXT:    vmov.32 r4, d31[0]
+; CHECK-NEXT:    movlt r6, #1
+; CHECK-NEXT:    cmp r6, #0
+; CHECK-NEXT:    mvnne r6, #0
+; CHECK-NEXT:    subs r2, r4, r2
+; CHECK-NEXT:    vmov.32 r4, d31[1]
+; CHECK-NEXT:    vmov.32 r2, d1[1]
+; CHECK-NEXT:    sbcs r2, r4, r2
+; CHECK-NEXT:    mov r2, #0
+; CHECK-NEXT:    movlt r2, #1
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    mvnne r2, #0
+; CHECK-NEXT:    vdup.32 d27, r2
+; CHECK-NEXT:    add r2, r0, #48
+; CHECK-NEXT:    vld1.64 {d4, d5}, [r2:128]
+; CHECK-NEXT:    add r2, r1, #48
+; CHECK-NEXT:    add r0, r0, #80
+; CHECK-NEXT:    add r1, r1, #80
+; CHECK-NEXT:    vld1.64 {d6, d7}, [r2:128]
+; CHECK-NEXT:    vmov.32 r2, d7[0]
+; CHECK-NEXT:    vmov.32 r4, d5[0]
+; CHECK-NEXT:    vmov.32 r5, d4[0]
+; CHECK-NEXT:    vld1.64 {d8, d9}, [r0:128]
+; CHECK-NEXT:    subs r2, r4, r2
+; CHECK-NEXT:    vmov.32 r4, d5[1]
+; CHECK-NEXT:    vmov.32 r2, d7[1]
+; CHECK-NEXT:    sbcs r2, r4, r2
+; CHECK-NEXT:    vmov.32 r4, d0[0]
+; CHECK-NEXT:    mov r2, #0
+; CHECK-NEXT:    movlt r2, #1
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    mvnne r2, #0
+; CHECK-NEXT:    vdup.32 d29, r2
+; CHECK-NEXT:    vmov.32 r2, d6[1]
+; CHECK-NEXT:    subs r4, r7, r4
+; CHECK-NEXT:    vmov.32 r7, d30[1]
+; CHECK-NEXT:    vmov.32 r4, d0[1]
+; CHECK-NEXT:    sbcs r4, r7, r4
+; CHECK-NEXT:    vmov.32 r7, d4[1]
+; CHECK-NEXT:    mov r4, #0
+; CHECK-NEXT:    movlt r4, #1
+; CHECK-NEXT:    cmp r4, #0
+; CHECK-NEXT:    mvnne r4, #0
+; CHECK-NEXT:    vdup.32 d26, r4
+; CHECK-NEXT:    vmov.32 r4, d6[0]
+; CHECK-NEXT:    vbsl q13, q15, q0
+; CHECK-NEXT:    vld1.64 {d0, d1}, [r9:128]
+; CHECK-NEXT:    vdup.32 d31, r6
+; CHECK-NEXT:    vmov.32 r9, d3[0]
+; CHECK-NEXT:    vdup.32 d30, r10
+; CHECK-NEXT:    vmov.32 r10, d21[1]
+; CHECK-NEXT:    vbsl q15, q11, q12
+; CHECK-NEXT:    subs r4, r5, r4
+; CHECK-NEXT:    sbcs r2, r7, r2
+; CHECK-NEXT:    vmov.32 r4, d0[1]
+; CHECK-NEXT:    mov r2, #0
+; CHECK-NEXT:    movlt r2, #1
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    mvnne r2, #0
+; CHECK-NEXT:    vdup.32 d28, r2
+; CHECK-NEXT:    vbsl q14, q2, q3
+; CHECK-NEXT:    vld1.64 {d4, d5}, [r8:128]
+; CHECK-NEXT:    vmov.32 r2, d0[0]
+; CHECK-NEXT:    vmov.32 r6, d4[0]
+; CHECK-NEXT:    vmov.32 r5, d4[1]
+; CHECK-NEXT:    vld1.64 {d6, d7}, [r1:128]
+; CHECK-NEXT:    vmov.32 r7, d7[0]
+; CHECK-NEXT:    vmov.32 r1, d7[1]
+; CHECK-NEXT:    vmov.32 lr, d5[0]
+; CHECK-NEXT:    vmov.32 r8, d3[1]
+; CHECK-NEXT:    subs r0, r6, r2
+; CHECK-NEXT:    vmov.32 r2, d9[1]
+; CHECK-NEXT:    sbcs r0, r5, r4
+; CHECK-NEXT:    vmov.32 r4, d9[0]
+; CHECK-NEXT:    movlt r3, #1
+; CHECK-NEXT:    cmp r3, #0
+; CHECK-NEXT:    mvnne r3, #0
+; CHECK-NEXT:    vmov.32 r6, d8[1]
+; CHECK-NEXT:    mov r5, #0
+; CHECK-NEXT:    vmov.32 r0, d5[1]
+; CHECK-NEXT:    subs r4, r4, r7
+; CHECK-NEXT:    vmov.32 r7, d2[1]
+; CHECK-NEXT:    sbcs r1, r2, r1
+; CHECK-NEXT:    vmov.32 r2, d8[0]
+; CHECK-NEXT:    vmov.32 r1, d6[0]
+; CHECK-NEXT:    movlt r5, #1
+; CHECK-NEXT:    vmov.32 r4, d6[1]
+; CHECK-NEXT:    cmp r5, #0
+; CHECK-NEXT:    mvnne r5, #0
+; CHECK-NEXT:    vdup.32 d11, r5
+; CHECK-NEXT:    vmov.32 r5, d20[0]
+; CHECK-NEXT:    subs r1, r2, r1
+; CHECK-NEXT:    vmov.32 r2, d1[0]
+; CHECK-NEXT:    sbcs r1, r6, r4
+; CHECK-NEXT:    vmov.32 r6, d1[1]
+; CHECK-NEXT:    vmov.32 r4, d20[1]
+; CHECK-NEXT:    mov r1, #0
+; CHECK-NEXT:    movlt r1, #1
+; CHECK-NEXT:    cmp r1, #0
+; CHECK-NEXT:    mvnne r1, #0
+; CHECK-NEXT:    vdup.32 d10, r1
+; CHECK-NEXT:    mov r1, #0
+; CHECK-NEXT:    vbsl q5, q4, q3
+; CHECK-NEXT:    subs r2, lr, r2
+; CHECK-NEXT:    sbcs r0, r0, r6
+; CHECK-NEXT:    mov r0, #0
+; CHECK-NEXT:    movlt r0, #1
+; CHECK-NEXT:    subs r2, r5, r12
+; CHECK-NEXT:    sbcs r2, r4, r7
+; CHECK-NEXT:    mov r2, #0
+; CHECK-NEXT:    movlt r2, #1
+; CHECK-NEXT:    subs r7, r11, r9
+; CHECK-NEXT:    sbcs r7, r10, r8
+; CHECK-NEXT:    movlt r1, #1
+; CHECK-NEXT:    cmp r1, #0
+; CHECK-NEXT:    mvnne r1, #0
+; CHECK-NEXT:    cmp r2, #0
+; CHECK-NEXT:    vdup.32 d23, r1
+; CHECK-NEXT:    mvnne r2, #0
+; CHECK-NEXT:    cmp r0, #0
+; CHECK-NEXT:    ldr r1, [sp, #4] @ 4-byte Reload
+; CHECK-NEXT:    mvnne r0, #0
+; CHECK-NEXT:    vdup.32 d22, r2
+; CHECK-NEXT:    vdup.32 d25, r0
+; CHECK-NEXT:    add r0, r1, #80
+; CHECK-NEXT:    vbsl q11, q10, q1
+; CHECK-NEXT:    vdup.32 d24, r3
+; CHECK-NEXT:    vst1.64 {d10, d11}, [r0:128]
+; CHECK-NEXT:    add r0, r1, #32
+; CHECK-NEXT:    vbsl q12, q2, q0
+; CHECK-NEXT:    vst1.64 {d30, d31}, [r0:128]
+; CHECK-NEXT:    add r0, r1, #48
+; CHECK-NEXT:    vst1.64 {d28, d29}, [r0:128]
+; CHECK-NEXT:    add r0, r1, #64
+; CHECK-NEXT:    vst1.64 {d18, d19}, [r1:128]!
+; CHECK-NEXT:    vst1.64 {d26, d27}, [r1:128]
+; CHECK-NEXT:    mov r1, #32
+; CHECK-NEXT:    vst1.64 {d16, d17}, [r0:128], r1
+; CHECK-NEXT:    vst1.64 {d22, d23}, [r0:128]!
+; CHECK-NEXT:    vst1.64 {d24, d25}, [r0:128]
+; CHECK-NEXT:    add sp, sp, #8
+; CHECK-NEXT:    vpop {d8, d9, d10, d11}
+; CHECK-NEXT:    add sp, sp, #4
+; CHECK-NEXT:    pop {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+; CHECK-NEXT:    mov pc, lr
   %v0 = load %T0_20, %T0_20* %loadaddr
   %v1 = load %T0_20, %T0_20* %loadaddr2
   %c = icmp slt %T0_20 %v0, %v1
diff --git a/llvm/test/CodeGen/Thumb2/float-intrinsics-double.ll b/llvm/test/CodeGen/Thumb2/float-intrinsics-double.ll
index acafde53ac830..611a9c1500d82 100644
--- a/llvm/test/CodeGen/Thumb2/float-intrinsics-double.ll
+++ b/llvm/test/CodeGen/Thumb2/float-intrinsics-double.ll
@@ -127,9 +127,11 @@ define double @copysign_d(double %a, double %b) {
 ; SOFT: bfi r1, [[REG]], #31, #1
 ; VFP: lsrs [[REG:r[0-9]+]], r3, #31
 ; VFP: bfi r1, [[REG]], #31, #1
-; NEON: vmov.i32 [[REG:d[0-9]+]], #0x80000000
-; NEON: vshl.i64 [[REG]], [[REG]], #32
-; NEON: vbsl [[REG]], d
+; NEON:         vmov.i32 d16, #0x80000000
+; NEON-NEXT:    vshl.i64 d16, d16, #32
+; NEON-NEXT:    vbsl d16, d1, d0
+; NEON-NEXT:    vorr d0, d16, d16
+; NEON-NEXT:    bx lr
   %1 = call double @llvm.copysign.f64(double %a, double %b)
   ret double %1
 }
diff --git a/llvm/test/CodeGen/Thumb2/float-intrinsics-float.ll b/llvm/test/CodeGen/Thumb2/float-intrinsics-float.ll
index 1263ae15b4664..5e8276f071159 100644
--- a/llvm/test/CodeGen/Thumb2/float-intrinsics-float.ll
+++ b/llvm/test/CodeGen/Thumb2/float-intrinsics-float.ll
@@ -3,8 +3,8 @@
 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-m33                   | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=SP -check-prefix=NO-VMLA
 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-m7                    | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=VFP  -check-prefix=FP-ARMv8  -check-prefix=VMLA
 ; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-m7 -mattr=-fp64 | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=SP -check-prefix=FP-ARMv8 -check-prefix=VMLA
-; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-a7                    | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=NEON -check-prefix=VFP4 -check-prefix=NO-VMLA
-; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-a57                   | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=NEON -check-prefix=FP-ARMv8 -check-prefix=VMLA
+; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-a7                    | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=NEON-A7 -check-prefix=VFP4 -check-prefix=NO-VMLA
+; RUN: llc < %s -mtriple=thumbv7-none-eabihf -mcpu=cortex-a57                   | FileCheck %s -check-prefix=CHECK -check-prefix=HARD -check-prefix=DP -check-prefix=NEON-A57 -check-prefix=FP-ARMv8 -check-prefix=VMLA
 
 declare float     @llvm.sqrt.f32(float %Val)
 define float @sqrt_f(float %a) {
@@ -123,8 +123,20 @@ define float @copysign_f(float %a, float %b) {
 ; SP: bfi r{{[0-9]+}}, [[REG]], #31, #1
 ; VFP: lsrs [[REG:r[0-9]+]], r{{[0-9]+}}, #31
 ; VFP: bfi r{{[0-9]+}}, [[REG]], #31, #1
-; NEON: vmov.i32 [[REG:d[0-9]+]], #0x80000000
-; NEON: vbsl [[REG]], d
+; NEON-A7:       @ %bb.0:
+; NEON-A7-NEXT:    vmov.f32 s4, s1
+; NEON-A7-NEXT:    @ kill: def $s0 killed $s0 def $d0
+; NEON-A7-NEXT:    vmov.i32 d1, #0x80000000
+; NEON-A7-NEXT:    vbsl d1, d2, d0
+; NEON-A7-NEXT:    vmov.f32 s0, s2
+; NEON-A7-NEXT:    bx lr
+; NEON-A57:       @ %bb.0:
+; NEON-A57-NEXT:    vmov.f32 s4, s1
+; NEON-A57-NEXT:    vmov.i32 d1, #0x80000000
+; NEON-A57-NEXT:    @ kill: def $s0 killed $s0 def $d0
+; NEON-A57-NEXT:    vbsl d1, d2, d0
+; NEON-A57-NEXT:    vmov.f32 s0, s2
+; NEON-A57-NEXT:    bx lr
   %1 = call float @llvm.copysign.f32(float %a, float %b)
   ret float %1
 }

From 69fff1fc498fe9bcb1ac6d0aa01bd825860e32f3 Mon Sep 17 00:00:00 2001
From: Sanjay Patel 
Date: Mon, 13 Jul 2020 11:23:45 -0400
Subject: [PATCH 115/771] [x86] add tests for bswap/rotate; NFC

---
 llvm/test/CodeGen/X86/rot16.ll | 72 +++++++++++++++++++++++++++++++++-
 1 file changed, 70 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/X86/rot16.ll b/llvm/test/CodeGen/X86/rot16.ll
index 5a1a8da3c677b..f0cd650624c6f 100644
--- a/llvm/test/CodeGen/X86/rot16.ll
+++ b/llvm/test/CodeGen/X86/rot16.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X32
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64
+; RUN: llc < %s -mtriple=i686--                | FileCheck %s --check-prefixes=X32,BASE32
+; RUN: llc < %s -mtriple=i686--  -mattr=movbe  | FileCheck %s --check-prefixes=X32,MOVBE32
+; RUN: llc < %s -mtriple=x86_64--              | FileCheck %s --check-prefixes=X64,BASE64
+; RUN: llc < %s -mtriple=x86_64-- -mattr=movbe | FileCheck %s --check-prefixes=X64,MOVBE64
 
 define i16 @foo(i16 %x, i16 %y, i16 %z) nounwind {
 ; X32-LABEL: foo:
@@ -230,3 +232,69 @@ define i16 @rot16_trunc(i32 %x, i32 %y) nounwind {
 	%t3 = trunc i32 %t2 to i16
 	ret i16 %t3
 }
+
+define i16 @rotate16(i16 %x) {
+; X32-LABEL: rotate16:
+; X32:       # %bb.0:
+; X32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
+; X32-NEXT:    rolw $8, %ax
+; X32-NEXT:    retl
+;
+; X64-LABEL: rotate16:
+; X64:       # %bb.0:
+; X64-NEXT:    movl %edi, %eax
+; X64-NEXT:    rolw $8, %ax
+; X64-NEXT:    # kill: def $ax killed $ax killed $eax
+; X64-NEXT:    retq
+  %r = call i16 @llvm.fshl.i16(i16 %x, i16 %x, i16 8)
+  ret i16 %r
+}
+
+define void @rotate16_in_place_memory(i8* %p) {
+; X32-LABEL: rotate16_in_place_memory:
+; X32:       # %bb.0:
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X32-NEXT:    rolw $8, (%eax)
+; X32-NEXT:    retl
+;
+; X64-LABEL: rotate16_in_place_memory:
+; X64:       # %bb.0:
+; X64-NEXT:    rolw $8, (%rdi)
+; X64-NEXT:    retq
+  %p0 = getelementptr i8, i8* %p, i64 0
+  %p1 = getelementptr i8, i8* %p, i64 1
+  %i0 = load i8, i8* %p0, align 1
+  %i1 = load i8, i8* %p1, align 1
+  store i8 %i1, i8* %p0, align 1
+  store i8 %i0, i8* %p1, align 1
+  ret void
+}
+
+define void @rotate16_memory(i8* %p, i8* %q) {
+; X32-LABEL: rotate16_memory:
+; X32:       # %bb.0:
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; X32-NEXT:    movzwl (%ecx), %ecx
+; X32-NEXT:    rolw $8, %cx
+; X32-NEXT:    movw %cx, (%eax)
+; X32-NEXT:    retl
+;
+; X64-LABEL: rotate16_memory:
+; X64:       # %bb.0:
+; X64-NEXT:    movzwl (%rdi), %eax
+; X64-NEXT:    rolw $8, %ax
+; X64-NEXT:    movw %ax, (%rsi)
+; X64-NEXT:    retq
+  %p0 = getelementptr i8, i8* %p, i64 0
+  %p1 = getelementptr i8, i8* %p, i64 1
+  %q0 = getelementptr i8, i8* %q, i64 0
+  %q1 = getelementptr i8, i8* %q, i64 1
+  %i0 = load i8, i8* %p0, align 1
+  %i1 = load i8, i8* %p1, align 1
+  store i8 %i1, i8* %q0, align 1
+  store i8 %i0, i8* %q1, align 1
+  ret void
+}
+
+declare i16 @llvm.fshl.i16(i16, i16, i16)

From 8779b114109dd1461a410e2357f2505665e6efec Mon Sep 17 00:00:00 2001
From: Sanjay Patel 
Date: Mon, 13 Jul 2020 11:35:38 -0400
Subject: [PATCH 116/771] [DAGCombiner] rot i16 X, 8 --> bswap X

We have this generic transform in IR (instcombine),
but as shown in PR41098:
http://bugs.llvm.org/PR41098
...the pattern may emerge in codegen too.

x86 has a potential refinement/reversal opportunity here,
but that should come later or needs a target hook to
avoid the transform. Converting to bswap is the more
specific form, so we should use it if it is available.
---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp |  6 ++
 llvm/test/CodeGen/X86/rot16.ll                | 90 +++++++++++++------
 2 files changed, 68 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index dd601bd5ca7e8..0dde1d0918e13 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -7694,6 +7694,12 @@ SDValue DAGCombiner::visitRotate(SDNode *N) {
       return DAG.getNode(N->getOpcode(), dl, VT, N0, Amt);
   }
 
+  // rot i16 X, 8 --> bswap X
+  auto *RotAmtC = isConstOrConstSplat(N1);
+  if (RotAmtC && RotAmtC->getAPIntValue() == 8 &&
+      VT.getScalarSizeInBits() == 16 && hasOperation(ISD::BSWAP, VT))
+    return DAG.getNode(ISD::BSWAP, dl, VT, N0);
+
   // Simplify the operands using demanded-bits information.
   if (SimplifyDemandedBits(SDValue(N, 0)))
     return SDValue(N, 0);
diff --git a/llvm/test/CodeGen/X86/rot16.ll b/llvm/test/CodeGen/X86/rot16.ll
index f0cd650624c6f..a6adb42242dda 100644
--- a/llvm/test/CodeGen/X86/rot16.ll
+++ b/llvm/test/CodeGen/X86/rot16.ll
@@ -234,11 +234,16 @@ define i16 @rot16_trunc(i32 %x, i32 %y) nounwind {
 }
 
 define i16 @rotate16(i16 %x) {
-; X32-LABEL: rotate16:
-; X32:       # %bb.0:
-; X32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
-; X32-NEXT:    rolw $8, %ax
-; X32-NEXT:    retl
+; BASE32-LABEL: rotate16:
+; BASE32:       # %bb.0:
+; BASE32-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
+; BASE32-NEXT:    rolw $8, %ax
+; BASE32-NEXT:    retl
+;
+; MOVBE32-LABEL: rotate16:
+; MOVBE32:       # %bb.0:
+; MOVBE32-NEXT:    movbew {{[0-9]+}}(%esp), %ax
+; MOVBE32-NEXT:    retl
 ;
 ; X64-LABEL: rotate16:
 ; X64:       # %bb.0:
@@ -250,17 +255,32 @@ define i16 @rotate16(i16 %x) {
   ret i16 %r
 }
 
+; TODO: Should this always be rolw with memory operand?
+
 define void @rotate16_in_place_memory(i8* %p) {
-; X32-LABEL: rotate16_in_place_memory:
-; X32:       # %bb.0:
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X32-NEXT:    rolw $8, (%eax)
-; X32-NEXT:    retl
+; BASE32-LABEL: rotate16_in_place_memory:
+; BASE32:       # %bb.0:
+; BASE32-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; BASE32-NEXT:    rolw $8, (%eax)
+; BASE32-NEXT:    retl
 ;
-; X64-LABEL: rotate16_in_place_memory:
-; X64:       # %bb.0:
-; X64-NEXT:    rolw $8, (%rdi)
-; X64-NEXT:    retq
+; MOVBE32-LABEL: rotate16_in_place_memory:
+; MOVBE32:       # %bb.0:
+; MOVBE32-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; MOVBE32-NEXT:    movzwl (%eax), %ecx
+; MOVBE32-NEXT:    movbew %cx, (%eax)
+; MOVBE32-NEXT:    retl
+;
+; BASE64-LABEL: rotate16_in_place_memory:
+; BASE64:       # %bb.0:
+; BASE64-NEXT:    rolw $8, (%rdi)
+; BASE64-NEXT:    retq
+;
+; MOVBE64-LABEL: rotate16_in_place_memory:
+; MOVBE64:       # %bb.0:
+; MOVBE64-NEXT:    movzwl (%rdi), %eax
+; MOVBE64-NEXT:    movbew %ax, (%rdi)
+; MOVBE64-NEXT:    retq
   %p0 = getelementptr i8, i8* %p, i64 0
   %p1 = getelementptr i8, i8* %p, i64 1
   %i0 = load i8, i8* %p0, align 1
@@ -271,21 +291,35 @@ define void @rotate16_in_place_memory(i8* %p) {
 }
 
 define void @rotate16_memory(i8* %p, i8* %q) {
-; X32-LABEL: rotate16_memory:
-; X32:       # %bb.0:
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %eax
-; X32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X32-NEXT:    movzwl (%ecx), %ecx
-; X32-NEXT:    rolw $8, %cx
-; X32-NEXT:    movw %cx, (%eax)
-; X32-NEXT:    retl
+; BASE32-LABEL: rotate16_memory:
+; BASE32:       # %bb.0:
+; BASE32-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; BASE32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; BASE32-NEXT:    movzwl (%ecx), %ecx
+; BASE32-NEXT:    rolw $8, %cx
+; BASE32-NEXT:    movw %cx, (%eax)
+; BASE32-NEXT:    retl
 ;
-; X64-LABEL: rotate16_memory:
-; X64:       # %bb.0:
-; X64-NEXT:    movzwl (%rdi), %eax
-; X64-NEXT:    rolw $8, %ax
-; X64-NEXT:    movw %ax, (%rsi)
-; X64-NEXT:    retq
+; MOVBE32-LABEL: rotate16_memory:
+; MOVBE32:       # %bb.0:
+; MOVBE32-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; MOVBE32-NEXT:    movl {{[0-9]+}}(%esp), %ecx
+; MOVBE32-NEXT:    movzwl (%ecx), %ecx
+; MOVBE32-NEXT:    movbew %cx, (%eax)
+; MOVBE32-NEXT:    retl
+;
+; BASE64-LABEL: rotate16_memory:
+; BASE64:       # %bb.0:
+; BASE64-NEXT:    movzwl (%rdi), %eax
+; BASE64-NEXT:    rolw $8, %ax
+; BASE64-NEXT:    movw %ax, (%rsi)
+; BASE64-NEXT:    retq
+;
+; MOVBE64-LABEL: rotate16_memory:
+; MOVBE64:       # %bb.0:
+; MOVBE64-NEXT:    movzwl (%rdi), %eax
+; MOVBE64-NEXT:    movbew %ax, (%rsi)
+; MOVBE64-NEXT:    retq
   %p0 = getelementptr i8, i8* %p, i64 0
   %p1 = getelementptr i8, i8* %p, i64 1
   %q0 = getelementptr i8, i8* %q, i64 0

From 153a0b8906d57f07f6711c2cfd10361616987038 Mon Sep 17 00:00:00 2001
From: Hiroshi Yamauchi 
Date: Tue, 7 Jul 2020 10:19:54 -0700
Subject: [PATCH 117/771] [PGO][PGSO] Add profile guided size optimization to
 the X86 LEA fixup.

Differential Revision: https://reviews.llvm.org/D83330
---
 llvm/lib/Target/X86/X86FixupLEAs.cpp        | 19 +++++-
 llvm/lib/Target/X86/X86PadShortFunction.cpp |  1 +
 llvm/test/CodeGen/X86/fixup-lea.ll          | 74 +++++++--------------
 3 files changed, 42 insertions(+), 52 deletions(-)

diff --git a/llvm/lib/Target/X86/X86FixupLEAs.cpp b/llvm/lib/Target/X86/X86FixupLEAs.cpp
index 9ac401bb02537..4242790389219 100644
--- a/llvm/lib/Target/X86/X86FixupLEAs.cpp
+++ b/llvm/lib/Target/X86/X86FixupLEAs.cpp
@@ -16,8 +16,11 @@
 #include "X86InstrInfo.h"
 #include "X86Subtarget.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/ProfileSummaryInfo.h"
+#include "llvm/CodeGen/LazyMachineBlockFrequencyInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineSizeOpts.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/TargetSchedule.h"
 #include "llvm/Support/Debug.h"
@@ -111,6 +114,12 @@ class FixupLEAPass : public MachineFunctionPass {
         MachineFunctionProperties::Property::NoVRegs);
   }
 
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.addRequired();
+    AU.addRequired();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+
 private:
   TargetSchedModel TSM;
   const X86InstrInfo *TII = nullptr;
@@ -205,21 +214,27 @@ bool FixupLEAPass::runOnMachineFunction(MachineFunction &MF) {
   TSM.init(&ST);
   TII = ST.getInstrInfo();
   TRI = ST.getRegisterInfo();
+  auto *PSI = &getAnalysis().getPSI();
+  auto *MBFI = (PSI && PSI->hasProfileSummary())
+                   ? &getAnalysis().getBFI()
+                   : nullptr;
 
   LLVM_DEBUG(dbgs() << "Start X86FixupLEAs\n";);
   for (MachineBasicBlock &MBB : MF) {
     // First pass. Try to remove or optimize existing LEAs.
+    bool OptIncDecPerBB =
+        OptIncDec || llvm::shouldOptimizeForSize(&MBB, PSI, MBFI);
     for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
       if (!isLEA(I->getOpcode()))
         continue;
 
-      if (optTwoAddrLEA(I, MBB, OptIncDec, UseLEAForSP))
+      if (optTwoAddrLEA(I, MBB, OptIncDecPerBB, UseLEAForSP))
         continue;
 
       if (IsSlowLEA)
         processInstructionForSlowLEA(I, MBB);
       else if (IsSlow3OpsLEA)
-        processInstrForSlow3OpLEA(I, MBB, OptIncDec);
+        processInstrForSlow3OpLEA(I, MBB, OptIncDecPerBB);
     }
 
     // Second pass for creating LEAs. This may reverse some of the
diff --git a/llvm/lib/Target/X86/X86PadShortFunction.cpp b/llvm/lib/Target/X86/X86PadShortFunction.cpp
index 4c6bd0ccc2cd2..ec81b07f9e5f0 100644
--- a/llvm/lib/Target/X86/X86PadShortFunction.cpp
+++ b/llvm/lib/Target/X86/X86PadShortFunction.cpp
@@ -58,6 +58,7 @@ namespace {
     void getAnalysisUsage(AnalysisUsage &AU) const override {
       AU.addRequired();
       AU.addRequired();
+      AU.addPreserved();
       MachineFunctionPass::getAnalysisUsage(AU);
     }
 
diff --git a/llvm/test/CodeGen/X86/fixup-lea.ll b/llvm/test/CodeGen/X86/fixup-lea.ll
index 3f661a8e991e9..35c3976408f64 100644
--- a/llvm/test/CodeGen/X86/fixup-lea.ll
+++ b/llvm/test/CodeGen/X86/fixup-lea.ll
@@ -109,31 +109,18 @@ for.end:
 }
 
 define void @foo_pgso(i32 inreg %dns) !prof !14 {
-; SLOW-LABEL: foo_pgso:
-; SLOW:       # %bb.0: # %entry
-; SLOW-NEXT:    xorl %ecx, %ecx
-; SLOW-NEXT:    decl %ecx
-; SLOW-NEXT:  .LBB4_1: # %for.body
-; SLOW-NEXT:    # =>This Inner Loop Header: Depth=1
-; SLOW-NEXT:    movzwl %cx, %edx
-; SLOW-NEXT:    decl %ecx
-; SLOW-NEXT:    cmpl %eax, %edx
-; SLOW-NEXT:    jl .LBB4_1
-; SLOW-NEXT:  # %bb.2: # %for.end
-; SLOW-NEXT:    retl
-;
-; FAST-LABEL: foo_pgso:
-; FAST:       # %bb.0: # %entry
-; FAST-NEXT:    xorl %ecx, %ecx
-; FAST-NEXT:    decl %ecx
-; FAST-NEXT:  .LBB4_1: # %for.body
-; FAST-NEXT:    # =>This Inner Loop Header: Depth=1
-; FAST-NEXT:    movzwl %cx, %edx
-; FAST-NEXT:    addl $-1, %ecx
-; FAST-NEXT:    cmpl %eax, %edx
-; FAST-NEXT:    jl .LBB4_1
-; FAST-NEXT:  # %bb.2: # %for.end
-; FAST-NEXT:    retl
+; CHECK-LABEL: foo_pgso:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    decl %ecx
+; CHECK-NEXT:  .LBB4_1: # %for.body
+; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    movzwl %cx, %edx
+; CHECK-NEXT:    decl %ecx
+; CHECK-NEXT:    cmpl %eax, %edx
+; CHECK-NEXT:    jl .LBB4_1
+; CHECK-NEXT:  # %bb.2: # %for.end
+; CHECK-NEXT:    retl
 entry:
   br label %for.body
 
@@ -149,31 +136,18 @@ for.end:
 }
 
 define void @bar_pgso(i32 inreg %dns) !prof !14 {
-; SLOW-LABEL: bar_pgso:
-; SLOW:       # %bb.0: # %entry
-; SLOW-NEXT:    xorl %ecx, %ecx
-; SLOW-NEXT:    incl %ecx
-; SLOW-NEXT:  .LBB5_1: # %for.body
-; SLOW-NEXT:    # =>This Inner Loop Header: Depth=1
-; SLOW-NEXT:    movzwl %cx, %edx
-; SLOW-NEXT:    incl %ecx
-; SLOW-NEXT:    cmpl %eax, %edx
-; SLOW-NEXT:    jl .LBB5_1
-; SLOW-NEXT:  # %bb.2: # %for.end
-; SLOW-NEXT:    retl
-;
-; FAST-LABEL: bar_pgso:
-; FAST:       # %bb.0: # %entry
-; FAST-NEXT:    xorl %ecx, %ecx
-; FAST-NEXT:    incl %ecx
-; FAST-NEXT:  .LBB5_1: # %for.body
-; FAST-NEXT:    # =>This Inner Loop Header: Depth=1
-; FAST-NEXT:    movzwl %cx, %edx
-; FAST-NEXT:    addl $1, %ecx
-; FAST-NEXT:    cmpl %eax, %edx
-; FAST-NEXT:    jl .LBB5_1
-; FAST-NEXT:  # %bb.2: # %for.end
-; FAST-NEXT:    retl
+; CHECK-LABEL: bar_pgso:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    xorl %ecx, %ecx
+; CHECK-NEXT:    incl %ecx
+; CHECK-NEXT:  .LBB5_1: # %for.body
+; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
+; CHECK-NEXT:    movzwl %cx, %edx
+; CHECK-NEXT:    incl %ecx
+; CHECK-NEXT:    cmpl %eax, %edx
+; CHECK-NEXT:    jl .LBB5_1
+; CHECK-NEXT:  # %bb.2: # %for.end
+; CHECK-NEXT:    retl
 entry:
   br label %for.body
 

From 83080a294ad7d145d758821bcf4354ad0cb7d299 Mon Sep 17 00:00:00 2001
From: Mircea Trofin 
Date: Mon, 29 Jun 2020 11:37:06 -0700
Subject: [PATCH 118/771] [llvm] Native size estimator for training -Oz inliner

Summary:
This is an experimental ML-based native size estimator, necessary for
computing partial rewards during -Oz inliner policy training. Data
extraction for model training will be provided in a separate patch.

RFC: http://lists.llvm.org/pipermail/llvm-dev/2020-April/140763.html

Reviewers: davidxl, jdoerfert

Subscribers: mgorny, hiraditya, mgrang, arphaman, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D82817
---
 llvm/CMakeLists.txt                           |    12 +
 .../Analysis/InlineSizeEstimatorAnalysis.h    |    35 +
 llvm/include/llvm/Analysis/Utils/TFUtils.h    |   136 +
 llvm/lib/Analysis/CMakeLists.txt              |    40 +-
 .../Analysis/InlineSizeEstimatorAnalysis.cpp  |   299 +
 llvm/lib/Analysis/TFUtils.cpp                 |   143 +
 llvm/lib/Passes/PassBuilder.cpp               |     1 +
 llvm/lib/Passes/PassRegistry.def              |     1 +
 llvm/unittests/Analysis/CMakeLists.txt        |    12 +-
 .../InlineSizeEstimatorAnalysisTest.cpp       |   101 +
 .../ir2native_x86_64_model/saved_model.pbtxt  | 10596 ++++++++++++++++
 .../variables/variables.data-00000-of-00001   |   Bin 0 -> 88424 bytes
 .../variables/variables.index                 |   Bin 0 -> 398 bytes
 llvm/unittests/Analysis/TFUtilsTest.cpp       |    98 +
 14 files changed, 11464 insertions(+), 10 deletions(-)
 create mode 100644 llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h
 create mode 100644 llvm/include/llvm/Analysis/Utils/TFUtils.h
 create mode 100644 llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp
 create mode 100644 llvm/lib/Analysis/TFUtils.cpp
 create mode 100644 llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp
 create mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt
 create mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001
 create mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index
 create mode 100644 llvm/unittests/Analysis/TFUtilsTest.cpp

diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index de2887b64c2a9..4e14e61fcacd6 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -981,6 +981,18 @@ if (NOT TENSORFLOW_AOT_PATH STREQUAL "")
     ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/tf_runtime)
 endif()
 
+set(TENSORFLOW_C_LIB_PATH "" CACHE PATH "Path to TensorFlow C library install")
+find_library(tensorflow_c_api tensorflow PATHS ${TENSORFLOW_C_LIB_PATH}/lib)
+
+# Similar to the above Tensorflow dependency, please refer to the same script.
+# In this case, the latest C API library is available for download from
+# https://www.tensorflow.org/install/lang_c
+if (tensorflow_c_api)
+  set(LLVM_HAVE_TF_API "ON" CACHE BOOL "Full Tensorflow API available")
+  add_definitions("-DLLVM_HAVE_TF_API")
+  include_directories(${TENSORFLOW_C_LIB_PATH}/include)
+endif()
+
 # Put this before tblgen. Else we have a circular dependence.
 add_subdirectory(lib/Demangle)
 add_subdirectory(lib/Support)
diff --git a/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h b/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h
new file mode 100644
index 0000000000000..29a6f59146748
--- /dev/null
+++ b/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h
@@ -0,0 +1,35 @@
+//===- InlineSizeEstimatorAnalysis.h - ML size estimator --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+
+#ifndef LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H
+#define LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H
+
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class Function;
+
+class TFModelEvaluator;
+class InlineSizeEstimatorAnalysis
+    : public AnalysisInfoMixin {
+public:
+  InlineSizeEstimatorAnalysis();
+  InlineSizeEstimatorAnalysis(InlineSizeEstimatorAnalysis &&);
+  ~InlineSizeEstimatorAnalysis();
+
+  static AnalysisKey Key;
+  using Result = Optional;
+  Result run(const Function &F, FunctionAnalysisManager &FAM);
+  static bool isEvaluatorRequested();
+
+private:
+  std::unique_ptr Evaluator;
+};
+} // namespace llvm
+#endif // LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H
\ No newline at end of file
diff --git a/llvm/include/llvm/Analysis/Utils/TFUtils.h b/llvm/include/llvm/Analysis/Utils/TFUtils.h
new file mode 100644
index 0000000000000..a1d7108b149ff
--- /dev/null
+++ b/llvm/include/llvm/Analysis/Utils/TFUtils.h
@@ -0,0 +1,136 @@
+//===- TFUtils.h - utilities for tensorflow C API ---------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+#ifndef LLVM_ANALYSIS_UTILS_TFUTILS_H
+#define LLVM_ANALYSIS_UTILS_TFUTILS_H
+
+#include "tensorflow/c/c_api.h"
+#include "llvm/IR/LLVMContext.h"
+
+#include 
+#include 
+
+namespace llvm {
+
+/// Load a SavedModel, find the given inputs and outputs, and setup storage
+/// for input tensors. The user is responsible for correctly dimensioning the
+/// input tensors and setting their values before calling evaluate().
+/// To initialize:
+/// - construct the object
+/// - initialize the input tensors using initInput. Indices must correspond to
+///   indices in the InputNames used at construction.
+/// To use:
+/// - set input values by using getInput to get each input tensor, and then
+///   setting internal scalars, for all dimensions (tensors are row-major:
+///   https://github.com/tensorflow/tensorflow/blob/r1.5/tensorflow/c/c_api.h#L205)
+/// - prepare an output vector of TF_Output* type, with the correct number of
+/// outputs (i.e. same as OutputNames). Initialize the vector with nullptr
+/// values.
+/// - call evaluate. The input tensors' values are not consumed after this, and
+///   may still be read.
+/// - use the outputs in the output vector
+/// - deallocate each output tensor in the output vector, using TF_DeleteTensor.
+class TFModelEvaluator final {
+public:
+  /// The result of a model evaluation. Handles the lifetime of the output
+  /// TF_Tensor objects, which means that their values need to be used before
+  /// the EvaluationResult's dtor is called.
+  class EvaluationResult {
+  public:
+    ~EvaluationResult() {
+      for (auto *P : Output)
+        if (P)
+          TF_DeleteTensor(P);
+    }
+
+    EvaluationResult(const EvaluationResult &) = delete;
+    EvaluationResult(EvaluationResult &&Other)
+        : OutputSize(Other.OutputSize), Output(std::move(Other.Output)) {
+      Other.Output.clear();
+    };
+
+    /// Get a pointer to the first element of the tensor at Index.
+    template  T *getTensorValue(size_t Index) {
+      return static_cast(TF_TensorData(Output[Index]));
+    }
+
+  private:
+    friend class TFModelEvaluator;
+    EvaluationResult(size_t OutputSize)
+        : OutputSize(OutputSize), Output(OutputSize){};
+
+    const size_t OutputSize;
+    std::vector Output;
+  };
+
+  using TFGraphPtr = std::unique_ptr;
+  using TFSessionOptionsPtr =
+      std::unique_ptr;
+  using TFStatusPtr = std::unique_ptr;
+
+  TFModelEvaluator(StringRef SavedModelPath,
+                   const std::vector &InputNames,
+                   const std::vector &OutputNames,
+                   const char *Tags = "serve");
+  ~TFModelEvaluator();
+  TFModelEvaluator(const TFModelEvaluator &) = delete;
+  TFModelEvaluator(TFModelEvaluator &&) = delete;
+
+  /// Evaluate the model, assuming it is valid. Returns None if the evaluation
+  /// fails or the model is invalid, or an EvaluationResult otherwise. The
+  /// inputs are assumed to have been already provided via getInput(). When
+  /// returning None, it also marks the object invalid. Pass an Output vector
+  /// with the same size as OutputNames, but with nullptr values. evaluate()
+  /// will populate it with tensors, matching in index the corresponding
+  /// OutputNames. The caller is responsible for the deallocation of those
+  /// tensors, using TF_DeleteTensor.
+  Optional evaluate();
+
+  /// Provides access to the input vector. It is already dimensioned correctly,
+  /// but the values need to be allocated by the user.
+  std::vector &getInput() { return Input; }
+
+  /// Returns true if the tensorflow model was loaded successfully, false
+  /// otherwise.
+  bool isValid() const { return !!Session; }
+
+  /// Initialize the input at Index as a tensor of the given type and dimensions
+  void initInput(int Index, TF_DataType Type,
+                 const std::vector &Dimensions);
+
+private:
+  /// The objects necessary for carrying out an evaluation of the SavedModel.
+  /// They are expensive to set up, and we maintain them accross all the
+  /// evaluations of the model.
+  TF_Session *Session = nullptr;
+  TFGraphPtr Graph;
+  TFSessionOptionsPtr Options;
+
+  /// The specification of the input nodes.
+  std::vector InputFeed;
+
+  /// The input tensors. They must match by index of the corresponding InputFeed
+  /// value. We set up the tensors once and just mutate theirs scalars before
+  /// each evaluation. The input tensors keep their value after an evaluation.
+  std::vector Input;
+
+  /// The specification of the output nodes. When evaluating, the tensors in the
+  /// output tensor vector must match by index the corresponding element in the
+  /// OutputFeed.
+  std::vector OutputFeed;
+
+  /// Reusable utility for deleting the session.
+  void deleteSession();
+
+  /// Reusable utility for ensuring we can bind the requested Name to a node in
+  /// the SavedModel Graph.
+  bool checkReportAndReset(const TF_Output &Output, StringRef Name);
+};
+} // namespace llvm
+
+#endif // LLVM_ANALYSIS_UTILS_TFUTILS_H
\ No newline at end of file
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index a317579ecc836..703623396d96a 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -1,17 +1,35 @@
 set(CommonMLSources MLInlineAdvisor.cpp)
 set(ReleaseModeMLSources ReleaseModeModelRunner.cpp)
+set(DevelopmentModeMLSources TFUtils.cpp)
 
-if (DEFINED LLVM_HAVE_TF_AOT)
-  include(TensorFlowCompile)
-  tfcompile(models/inliner serve action InlinerSizeModel llvm::InlinerSizeModel)
-  list(APPEND ReleaseModeMLSources
-    $
-    ${GENERATED_OBJS}
-  )
-  set(MLPolicySources ${CommonMLSources} ${ReleaseModeMLSources})
+if (DEFINED LLVM_HAVE_TF_AOT OR DEFINED LLVM_HAVE_TF_API)
+  set(MLPolicySources ${CommonMLSources})
+  if (DEFINED LLVM_HAVE_TF_AOT)
+    include(TensorFlowCompile)
+    tfcompile(models/inliner serve action InlinerSizeModel llvm::InlinerSizeModel)
+    list(APPEND ReleaseModeMLSources
+      $
+      ${GENERATED_OBJS}
+    )
+    LIST(APPEND MLPolicySources ${ReleaseModeMLSources})
+  else()
+    LIST(APPEND LLVM_OPTIONAL_SOURCES ${ReleaseModeMLSources})
+  endif()
+
+  if (DEFINED LLVM_HAVE_TF_API)
+    LIST(APPEND MLPolicySources ${DevelopmentModeMLSources})
+    LIST(APPEND MLLinkDeps ${tensorflow_c_api})
+  else()
+    LIST(APPEND LLVM_OPTIONAL_SOURCES ${DevelopmentModeMLSources})
+  endif()
 else()
-  set(LLVM_OPTIONAL_SOURCES ${CommonMLSources} ${ReleaseModeMLSources})
+  LIST(APPEND LLVM_OPTIONAL_SOURCES 
+    ${CommonMLSources}
+    ${DevelopmentModeMLSources}
+    ${ReleaseModeMLSources}
+    )
 endif()
+  
 
 add_llvm_component_library(LLVMAnalysis
   AliasAnalysis.cpp
@@ -57,6 +75,7 @@ add_llvm_component_library(LLVMAnalysis
   InlineCost.cpp
   InlineAdvisor.cpp
   InlineFeaturesAnalysis.cpp
+  InlineSizeEstimatorAnalysis.cpp
   InstCount.cpp
   InstructionPrecedenceTracking.cpp
   InstructionSimplify.cpp
@@ -124,4 +143,7 @@ add_llvm_component_library(LLVMAnalysis
 
   DEPENDS
   intrinsics_gen
+
+  LINK_LIBS
+  ${MLLinkDeps}
   )
diff --git a/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp b/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp
new file mode 100644
index 0000000000000..1d1952ae6cbbe
--- /dev/null
+++ b/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp
@@ -0,0 +1,299 @@
+//===- InlineSizeEstimatorAnalysis.cpp - IR to native size from ML model --===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This implements feature and label extraction for offline supervised learning
+// of a IR to native size model.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h"
+
+#ifdef LLVM_HAVE_TF_API
+#include "llvm/Analysis/Utils/TFUtils.h"
+#endif
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/MC/MCAsmLayout.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include 
+#include 
+
+using namespace llvm;
+
+AnalysisKey InlineSizeEstimatorAnalysis::Key;
+
+#define DEBUG_TYPE "inline-size-estimator"
+
+#ifdef LLVM_HAVE_TF_API
+cl::opt TFIR2NativeModelPath(
+    "ml-inliner-ir2native-model", cl::Hidden,
+    cl::desc("Path to saved model evaluating native size from IR."));
+
+namespace {
+unsigned getMaxInstructionID() {
+#define LAST_OTHER_INST(NR) return NR;
+#include "llvm/IR/Instruction.def"
+}
+
+class IRToNativeSizeLearning {
+public:
+  enum class NamedFeatureIndex : size_t {
+    InitialSize,
+    Blocks,
+    Calls,
+    IsLocal,
+    IsLinkOnceODR,
+    IsLinkOnce,
+    Loops,
+    MaxLoopDepth,
+    MaxDomTreeLevel,
+
+    NumNamedFeatures
+  };
+  static const size_t NumNamedFeatures =
+      static_cast(NamedFeatureIndex::NumNamedFeatures);
+  struct FunctionFeatures {
+    static std::vector>
+        ImportantInstructionSuccessions;
+    static const size_t FeatureCount;
+
+    std::array NamedFeatures = {0};
+    std::vector InstructionHistogram;
+    std::vector InstructionPairHistogram;
+
+    void fillTensor(int32_t *Ptr) const;
+    int32_t &operator[](NamedFeatureIndex Pos) {
+      return NamedFeatures[static_cast(Pos)];
+    }
+  };
+  IRToNativeSizeLearning() = default;
+
+  static FunctionFeatures getFunctionFeatures(Function &F,
+                                              FunctionAnalysisManager &FAM);
+
+private:
+  /// Sort once the feature tuples.
+  struct SortFeatureTuples {
+    bool IsSorted = false;
+    SortFeatureTuples() {
+      std::sort(FunctionFeatures::ImportantInstructionSuccessions.begin(),
+                FunctionFeatures::ImportantInstructionSuccessions.end());
+      IsSorted = true;
+    }
+  };
+
+  static llvm::ManagedStatic TupleSorter;
+
+  static bool ensureSortedTuples() { return TupleSorter->IsSorted; }
+};
+llvm::ManagedStatic
+    IRToNativeSizeLearning::TupleSorter;
+
+// This is a point in time - we determined including these pairs of
+// consecutive instructions (in the IR layout available at inline time) as
+// features improves the model performance. We want to move away from manual
+// feature selection.
+// The vector is given in opcode pairs rather than labels because 1) labels
+// weren't readily available, and 2) the successions were hand - extracted
+std::vector>
+    IRToNativeSizeLearning::FunctionFeatures::ImportantInstructionSuccessions =
+        {{1, 34},  {15, 27}, {53, 53}, {53, 34}, {1, 11},  {32, 2},  {2, 48},
+         {28, 48}, {1, 45},  {49, 32}, {57, 56}, {55, 53}, {1, 28},  {57, 34},
+         {1, 1},   {32, 28}, {32, 15}, {49, 28}, {53, 1},  {2, 53},  {48, 34},
+         {28, 53}, {2, 32},  {1, 40},  {32, 48}, {29, 56}, {56, 32}, {55, 56},
+         {48, 56}, {1, 31},  {33, 34}, {2, 28},  {1, 12},  {55, 1},  {31, 31},
+         {65, 1},  {33, 56}, {32, 32}, {13, 13}, {1, 26},  {13, 26}, {2, 1},
+         {1, 33},  {47, 49}, {64, 1},  {2, 38},  {34, 53}, {48, 2},  {55, 34},
+         {34, 32}, {1, 5},   {56, 13}, {2, 2},   {2, 49},  {33, 2},  {49, 39},
+         {56, 49}, {33, 49}, {32, 39}, {39, 57}, {29, 33}, {31, 34}, {32, 29},
+         {47, 15}, {13, 34}, {2, 33},  {32, 49}, {49, 34}, {56, 33}, {1, 30},
+         {33, 33}, {31, 33}, {2, 29},  {56, 7},  {32, 13}, {2, 55},  {56, 56},
+         {2, 34},  {1, 42},  {34, 49}, {1, 20},  {32, 33}, {1, 25},  {53, 28},
+         {1, 14},  {31, 49}, {28, 2},  {2, 13},  {2, 56},  {1, 32},  {56, 53},
+         {65, 65}, {33, 53}, {64, 64}, {13, 2},  {34, 33}, {1, 4},   {49, 2},
+         {1, 9},   {56, 1},  {33, 1},  {53, 57}, {32, 53}, {13, 56}, {32, 56},
+         {55, 55}, {1, 18},  {49, 56}, {34, 34}, {1, 7},   {56, 64}, {32, 1},
+         {13, 33}, {55, 28}, {49, 33}, {57, 57}, {56, 34}, {34, 56}, {33, 32},
+         {32, 40}, {1, 29},  {53, 2},  {34, 1},  {32, 34}, {49, 49}, {1, 24},
+         {40, 34}, {1, 13},  {38, 34}, {29, 2},  {34, 2},  {1, 39},  {1, 22},
+         {1, 27},  {49, 1},  {1, 8},   {56, 2}};
+
+// We have: 9 calculated features (the features here); 1 feature for each
+// instruction opcode; and 1 feature for each manually-identified sequence.
+// For the latter 2, we build a histogram: we count the number of
+// occurrences of each instruction opcode or succession of instructions,
+// respectively.
+// Note that instruction opcodes start from 1. For convenience, we also have an
+// always 0 feature for the '0' opcode, hence the extra 1.
+const size_t IRToNativeSizeLearning::FunctionFeatures::FeatureCount =
+    IRToNativeSizeLearning::FunctionFeatures::ImportantInstructionSuccessions
+        .size() +
+    getMaxInstructionID() + 1 + IRToNativeSizeLearning::NumNamedFeatures;
+
+size_t getSize(Function &F, TargetTransformInfo &TTI) {
+  size_t Ret = 0;
+  for (auto &BB : F)
+    for (auto &I : BB)
+      Ret += TTI.getInstructionCost(
+          &I, TargetTransformInfo::TargetCostKind::TCK_CodeSize);
+  return Ret;
+}
+
+size_t getSize(Function &F, FunctionAnalysisManager &FAM) {
+  auto &TTI = FAM.getResult(F);
+  return getSize(F, TTI);
+}
+
+unsigned getMaxDominatorTreeDepth(const Function &F,
+                                  const DominatorTree &Tree) {
+  unsigned Ret = 0;
+  for (auto &BB : F)
+    if (auto *TN = Tree.getNode(&BB))
+      Ret = std::max(Ret, TN->getLevel());
+  return Ret;
+}
+} // namespace
+
+IRToNativeSizeLearning::FunctionFeatures
+IRToNativeSizeLearning::getFunctionFeatures(Function &F,
+                                            FunctionAnalysisManager &FAM) {
+  assert(ensureSortedTuples() && "expected lazy initialization");
+
+  auto &DomTree = FAM.getResult(F);
+  FunctionFeatures FF;
+  size_t InstrCount = getMaxInstructionID() + 1;
+  FF.InstructionHistogram.resize(InstrCount);
+
+  FF.InstructionPairHistogram.resize(
+      FunctionFeatures::ImportantInstructionSuccessions.size());
+
+  auto StartID = 0;
+  auto LastID = StartID;
+  auto getPairIndex = [](size_t a, size_t b) {
+    auto I =
+        std::find(FunctionFeatures::ImportantInstructionSuccessions.begin(),
+                  FunctionFeatures::ImportantInstructionSuccessions.end(),
+                  std::make_pair(a, b));
+    if (I == FunctionFeatures::ImportantInstructionSuccessions.end())
+      return -1;
+    return static_cast(std::distance(
+        FunctionFeatures::ImportantInstructionSuccessions.begin(), I));
+  };
+
+  // We don't want debug calls, because they'd just add noise.
+  for (auto &BB : F) {
+    for (auto I = BB.instructionsWithoutDebug().begin(),
+              E = BB.instructionsWithoutDebug().end();
+         I != E; ++I) {
+      auto ID = I->getOpcode();
+
+      ++FF.InstructionHistogram[ID];
+      int PairIndex = getPairIndex(LastID, ID);
+      if (PairIndex >= 0)
+        ++FF.InstructionPairHistogram[PairIndex];
+      LastID = ID;
+      if (isa(*I))
+        ++FF[NamedFeatureIndex::Calls];
+    }
+  }
+
+  FF[NamedFeatureIndex::InitialSize] = getSize(F, FAM);
+  FF[NamedFeatureIndex::IsLocal] = F.hasLocalLinkage();
+  FF[NamedFeatureIndex::IsLinkOnceODR] = F.hasLinkOnceODRLinkage();
+  FF[NamedFeatureIndex::IsLinkOnce] = F.hasLinkOnceLinkage();
+  FF[NamedFeatureIndex::Blocks] =
+      std::distance(F.getBasicBlockList().begin(), F.getBasicBlockList().end());
+  auto &LI = FAM.getResult(F);
+  FF[NamedFeatureIndex::Loops] = std::distance(LI.begin(), LI.end());
+  for (auto &L : LI)
+    FF[NamedFeatureIndex::MaxLoopDepth] =
+        std::max(FF[NamedFeatureIndex::MaxLoopDepth],
+                 static_cast(L->getLoopDepth()));
+  FF[NamedFeatureIndex::MaxDomTreeLevel] = getMaxDominatorTreeDepth(F, DomTree);
+  return FF;
+}
+
+void IRToNativeSizeLearning::FunctionFeatures::fillTensor(int32_t *Ptr) const {
+  std::copy(NamedFeatures.begin(), NamedFeatures.end(), Ptr);
+  Ptr += NamedFeatures.size();
+  std::copy(InstructionHistogram.begin(), InstructionHistogram.end(), Ptr);
+  Ptr += InstructionHistogram.size();
+  std::copy(InstructionPairHistogram.begin(), InstructionPairHistogram.end(),
+            Ptr);
+}
+
+bool InlineSizeEstimatorAnalysis::isEvaluatorRequested() {
+  return !TFIR2NativeModelPath.empty();
+}
+
+InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis() {
+  if (!isEvaluatorRequested()) {
+    return;
+  }
+  std::vector InputNames{"serving_default_input_1"};
+  std::vector OutputName{"StatefulPartitionedCall"};
+  Evaluator = std::make_unique(
+      TFIR2NativeModelPath.getValue().c_str(), InputNames, OutputName);
+  if (!Evaluator || !Evaluator->isValid()) {
+    Evaluator.reset();
+    return;
+  }
+  static const std::vector Dim{
+      1, static_cast(
+             IRToNativeSizeLearning::FunctionFeatures::FeatureCount)};
+
+  Evaluator->initInput(0, TF_INT32, Dim);
+}
+
+InlineSizeEstimatorAnalysis::Result
+InlineSizeEstimatorAnalysis::run(const Function &F,
+                                 FunctionAnalysisManager &FAM) {
+  if (!Evaluator)
+    return None;
+  auto Features = IRToNativeSizeLearning::getFunctionFeatures(
+      const_cast(F), FAM);
+  int32_t *V = static_cast(TF_TensorData(Evaluator->getInput()[0]));
+  Features.fillTensor(V);
+  auto ER = Evaluator->evaluate();
+  if (!ER)
+    return None;
+  float Ret = *ER->getTensorValue(0);
+  if (Ret < 0.0)
+    Ret = 0.0;
+  return static_cast(Ret);
+}
+
+InlineSizeEstimatorAnalysis::~InlineSizeEstimatorAnalysis() {}
+InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis(
+    InlineSizeEstimatorAnalysis &&Other)
+    : Evaluator(std::move(Other.Evaluator)) {}
+
+#else
+namespace llvm {
+class TFModelEvaluator {};
+} // namespace llvm
+InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis() {}
+InlineSizeEstimatorAnalysis ::InlineSizeEstimatorAnalysis(
+    InlineSizeEstimatorAnalysis &&) {}
+InlineSizeEstimatorAnalysis::~InlineSizeEstimatorAnalysis() {}
+InlineSizeEstimatorAnalysis::Result
+InlineSizeEstimatorAnalysis::run(const Function &F,
+                                 FunctionAnalysisManager &FAM) {
+  return None;
+}
+bool InlineSizeEstimatorAnalysis::isEvaluatorRequested() { return false; }
+#endif
\ No newline at end of file
diff --git a/llvm/lib/Analysis/TFUtils.cpp b/llvm/lib/Analysis/TFUtils.cpp
new file mode 100644
index 0000000000000..6cd5b5c9b4eae
--- /dev/null
+++ b/llvm/lib/Analysis/TFUtils.cpp
@@ -0,0 +1,143 @@
+//===- TFUtils.cpp - tensorflow evaluation utilities ----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements utilities for interfacing with tensorflow C APIs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/Utils/TFUtils.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "tensorflow/c/c_api_experimental.h"
+
+#include 
+
+using namespace llvm;
+
+namespace {
+
+struct TFInitializer {
+  TFInitializer() {
+    assert(!IsInitialized && "TFInitialized should be called only once");
+    int Argc = 1;
+    const char *Name = "";
+    const char **NamePtr = &Name;
+    TF_InitMain(Name, &Argc, const_cast(&NamePtr));
+    IsInitialized = true;
+  }
+  bool IsInitialized = false;
+};
+
+llvm::ManagedStatic TFLibInitializer;
+
+bool ensureInitTF() { return TFLibInitializer->IsInitialized; }
+
+TFModelEvaluator::TFGraphPtr createTFGraph() {
+  return TFModelEvaluator::TFGraphPtr(TF_NewGraph(), &TF_DeleteGraph);
+}
+
+TFModelEvaluator::TFStatusPtr createTFStatus() {
+  return TFModelEvaluator::TFStatusPtr(TF_NewStatus(), &TF_DeleteStatus);
+}
+
+TFModelEvaluator::TFSessionOptionsPtr createTFSessionOptions() {
+  return TFModelEvaluator::TFSessionOptionsPtr(TF_NewSessionOptions(),
+                                               &TF_DeleteSessionOptions);
+}
+} // namespace
+
+TFModelEvaluator::TFModelEvaluator(StringRef SavedModelPath,
+                                   const std::vector &InputNames,
+                                   const std::vector &OutputNames,
+                                   const char *Tags)
+    : Graph(createTFGraph()), Options(createTFSessionOptions()),
+      InputFeed(InputNames.size()), Input(InputNames.size()),
+      OutputFeed(OutputNames.size()) {
+  if (!ensureInitTF()) {
+    errs() << "Tensorflow should have been initialized";
+    return;
+  }
+  auto Status = createTFStatus();
+
+  Session = TF_LoadSessionFromSavedModel(Options.get(), nullptr,
+                                         SavedModelPath.str().c_str(), &Tags, 1,
+                                         Graph.get(), nullptr, Status.get());
+  if (TF_GetCode(Status.get()) != TF_Code::TF_OK) {
+    errs() << TF_Message(Status.get());
+    deleteSession();
+  }
+  for (size_t I = 0; I < InputNames.size(); ++I) {
+    InputFeed[I] = {
+        TF_GraphOperationByName(Graph.get(), (InputNames[I]).c_str()), 0};
+    if (!checkReportAndReset(InputFeed[I], InputNames[I]))
+      return;
+  }
+  for (size_t I = 0; I < OutputNames.size(); ++I) {
+    OutputFeed[I] = {
+        TF_GraphOperationByName(Graph.get(), (OutputNames[I]).c_str()), 0};
+    if (!checkReportAndReset(OutputFeed[I], OutputNames[I]))
+      return;
+  }
+}
+
+TFModelEvaluator::~TFModelEvaluator() {
+  for (auto *T : Input) {
+    TF_DeleteTensor(T);
+  }
+  deleteSession();
+}
+
+bool TFModelEvaluator::checkReportAndReset(const TF_Output &Output,
+                                           StringRef Name) {
+  if (Output.oper)
+    return true;
+  errs() << "Could not find TF_Output named: " + Name;
+  deleteSession();
+  return false;
+}
+
+void TFModelEvaluator::deleteSession() {
+  if (Session == nullptr)
+    return;
+  auto Status = createTFStatus();
+  TF_DeleteSession(Session, Status.get());
+  Session = nullptr;
+  if (TF_GetCode(Status.get()) != TF_Code::TF_OK)
+    errs() << "Could not delete TF session";
+}
+
+Optional TFModelEvaluator::evaluate() {
+  if (!isValid())
+    return None;
+  EvaluationResult Ret(OutputFeed.size());
+  auto Status = createTFStatus();
+  TF_SessionRun(Session, nullptr, InputFeed.data(), Input.data(), Input.size(),
+                OutputFeed.data(), Ret.Output.data(), Ret.Output.size(),
+                nullptr, 0, nullptr, Status.get());
+  if (TF_GetCode(Status.get()) != TF_Code::TF_OK) {
+    errs() << TF_Message(Status.get());
+    deleteSession();
+    return None;
+  }
+  return Ret;
+}
+
+void TFModelEvaluator::initInput(int Index, TF_DataType Type,
+                                 const std::vector &Dimensions) {
+  int64_t TotalSize = TF_DataTypeSize(Type);
+  for (auto &D : Dimensions)
+    TotalSize *= D;
+
+  Input[Index] =
+      TF_AllocateTensor(Type, Dimensions.data(), Dimensions.size(), TotalSize);
+  std::memset(TF_TensorData(Input[Index]), 0, TotalSize);
+}
\ No newline at end of file
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 771cdfd17aa54..7f57634676956 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -35,6 +35,7 @@
 #include "llvm/Analysis/IVUsers.h"
 #include "llvm/Analysis/InlineAdvisor.h"
 #include "llvm/Analysis/InlineFeaturesAnalysis.h"
+#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h"
 #include "llvm/Analysis/LazyCallGraph.h"
 #include "llvm/Analysis/LazyValueInfo.h"
 #include "llvm/Analysis/LoopAccessAnalysis.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index eb2b740db5612..dfdfc3d05976a 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -133,6 +133,7 @@ FUNCTION_ANALYSIS("loops", LoopAnalysis())
 FUNCTION_ANALYSIS("lazy-value-info", LazyValueAnalysis())
 FUNCTION_ANALYSIS("da", DependenceAnalysis())
 FUNCTION_ANALYSIS("inliner-features", InlineFeaturesAnalysis())
+FUNCTION_ANALYSIS("inliner-size-estimator", InlineSizeEstimatorAnalysis())
 FUNCTION_ANALYSIS("memdep", MemoryDependenceAnalysis())
 FUNCTION_ANALYSIS("memoryssa", MemorySSAAnalysis())
 FUNCTION_ANALYSIS("phi-values", PhiValuesAnalysis())
diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt
index 42f7dd3c06101..59ad444d32fb4 100644
--- a/llvm/unittests/Analysis/CMakeLists.txt
+++ b/llvm/unittests/Analysis/CMakeLists.txt
@@ -6,7 +6,13 @@ set(LLVM_LINK_COMPONENTS
   TransformUtils
   )
 
-add_llvm_unittest(AnalysisTests
+if (DEFINED LLVM_HAVE_TF_API)
+  LIST(APPEND EXTRA_TESTS TFUtilsTest.cpp)
+else()
+  LIST(APPEND LLVM_OPTIONAL_SOURCES TFUtilsTest.cpp)
+endif()
+
+add_llvm_unittest_with_input_files(AnalysisTests
   AliasAnalysisTest.cpp
   AliasSetTrackerTest.cpp
   AssumeBundleQueriesTest.cpp
@@ -22,6 +28,7 @@ add_llvm_unittest(AnalysisTests
   DomTreeUpdaterTest.cpp
   GlobalsModRefTest.cpp
   InlineFeaturesAnalysisTest.cpp
+  InlineSizeEstimatorAnalysisTest.cpp
   IVDescriptorsTest.cpp
   LazyCallGraphTest.cpp
   LoadsTest.cpp
@@ -40,4 +47,7 @@ add_llvm_unittest(AnalysisTests
   ValueLatticeTest.cpp
   ValueTrackingTest.cpp
   VectorUtilsTest.cpp
+  ${EXTRA_TESTS}
   )
+
+ target_link_libraries(AnalysisTests PRIVATE LLVMTestingSupport)
diff --git a/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp b/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp
new file mode 100644
index 0000000000000..377590be016ac
--- /dev/null
+++ b/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp
@@ -0,0 +1,101 @@
+//===- InlineSizeEstimatorAnalysisTest.cpp - test for ir2native -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Testing/Support/SupportHelpers.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+extern const char *TestMainArgv0;
+extern cl::opt TFIR2NativeModelPath;
+
+#if LLVM_HAVE_TF_API
+static std::string getModelPath() {
+  SmallString<128> InputsDir = unittest::getInputFileDirectory(TestMainArgv0);
+  llvm::sys::path::append(InputsDir, "ir2native_x86_64_model");
+  return std::string(InputsDir);
+}
+#endif
+
+static std::unique_ptr parseIR(LLVMContext &C, const char *IR) {
+  SMDiagnostic Err;
+  std::unique_ptr Mod = parseAssemblyString(IR, Err, C);
+  if (!Mod)
+    Err.print("MLAnalysisTests", errs());
+  return Mod;
+}
+
+static FunctionAnalysisManager buildFAM() {
+  FunctionAnalysisManager FAM;
+  FAM.registerPass([&] { return DominatorTreeAnalysis(); });
+  FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+  FAM.registerPass([&] { return TargetIRAnalysis(); });
+  FAM.registerPass([&] { return LoopAnalysis(); });
+  return FAM;
+}
+
+// Test model loading and evaluation.
+TEST(InlineSizeEstimatorAnalysis, SizeIsValidTest) {
+  LLVMContext C;
+  std::unique_ptr M = parseIR(C,
+                                      R"IR(
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-linux-gnu"
+
+declare i32 @f1(i32)
+declare i32 @f2(i32)
+
+define i32 @branches(i32) {
+  %cond = icmp slt i32 %0, 3
+  br i1 %cond, label %then, label %else
+
+then:
+  %ret.1 = call i32 @f1(i32 %0)
+  br label %last.block
+
+else:
+  %ret.2 = call i32 @f2(i32 %0)
+  br label %last.block
+
+last.block:
+  %ret = phi i32 [%ret.1, %then], [%ret.2, %else]
+  ret i32 %ret
+}
+
+define internal i32 @top() {
+  %1 = call i32 @branches(i32 2)
+  %2 = call i32 @f1(i32 %1)
+  ret i32 %2
+}
+)IR");
+
+  FunctionAnalysisManager FAM = buildFAM();
+#if LLVM_HAVE_TF_API
+  TFIR2NativeModelPath = getModelPath();
+#endif
+
+  InlineSizeEstimatorAnalysis FA;
+  auto SizeEstimate = FA.run(*M->getFunction("branches"), FAM);
+#if LLVM_HAVE_TF_API
+  EXPECT_GT(*SizeEstimate, 0);
+#else
+  EXPECT_FALSE(SizeEstimate.hasValue());
+#endif
+}
diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt
new file mode 100644
index 0000000000000..6efdad51083d3
--- /dev/null
+++ b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt
@@ -0,0 +1,10596 @@
+saved_model_schema_version: 1
+meta_graphs {
+  meta_info_def {
+    stripped_op_list {
+      op {
+        name: "Const"
+        output_arg {
+          name: "output"
+          type_attr: "dtype"
+        }
+        attr {
+          name: "value"
+          type: "tensor"
+        }
+        attr {
+          name: "dtype"
+          type: "type"
+        }
+      }
+      op {
+        name: "NoOp"
+      }
+      op {
+        name: "Placeholder"
+        output_arg {
+          name: "output"
+          type_attr: "dtype"
+        }
+        attr {
+          name: "dtype"
+          type: "type"
+        }
+        attr {
+          name: "shape"
+          type: "shape"
+          default_value {
+            shape {
+              unknown_rank: true
+            }
+          }
+        }
+      }
+      op {
+        name: "ReadVariableOp"
+        input_arg {
+          name: "resource"
+          type: DT_RESOURCE
+        }
+        output_arg {
+          name: "value"
+          type_attr: "dtype"
+        }
+        attr {
+          name: "dtype"
+          type: "type"
+        }
+        is_stateful: true
+      }
+      op {
+        name: "StatefulPartitionedCall"
+        input_arg {
+          name: "args"
+          type_list_attr: "Tin"
+        }
+        output_arg {
+          name: "output"
+          type_list_attr: "Tout"
+        }
+        attr {
+          name: "Tin"
+          type: "list(type)"
+          has_minimum: true
+        }
+        attr {
+          name: "Tout"
+          type: "list(type)"
+          has_minimum: true
+        }
+        attr {
+          name: "f"
+          type: "func"
+        }
+        attr {
+          name: "config"
+          type: "string"
+          default_value {
+            s: ""
+          }
+        }
+        attr {
+          name: "config_proto"
+          type: "string"
+          default_value {
+            s: ""
+          }
+        }
+        attr {
+          name: "executor_type"
+          type: "string"
+          default_value {
+            s: ""
+          }
+        }
+        is_stateful: true
+      }
+      op {
+        name: "VarHandleOp"
+        output_arg {
+          name: "resource"
+          type: DT_RESOURCE
+        }
+        attr {
+          name: "container"
+          type: "string"
+          default_value {
+            s: ""
+          }
+        }
+        attr {
+          name: "shared_name"
+          type: "string"
+          default_value {
+            s: ""
+          }
+        }
+        attr {
+          name: "dtype"
+          type: "type"
+        }
+        attr {
+          name: "shape"
+          type: "shape"
+        }
+        is_stateful: true
+      }
+    }
+    tags: "serve"
+    tensorflow_version: "1.15.0"
+    tensorflow_git_version: "unknown"
+    stripped_default_attrs: true
+  }
+  graph_def {
+    node {
+      name: "dense/kernel"
+      op: "VarHandleOp"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+            dim {
+              size: 214
+            }
+            dim {
+              size: 100
+            }
+          }
+        }
+      }
+      attr {
+        key: "shared_name"
+        value {
+          s: "dense/kernel"
+        }
+      }
+    }
+    node {
+      name: "dense/kernel/Read/ReadVariableOp"
+      op: "ReadVariableOp"
+      input: "dense/kernel"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+              dim {
+                size: 214
+              }
+              dim {
+                size: 100
+              }
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+    }
+    node {
+      name: "dense/bias"
+      op: "VarHandleOp"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+            dim {
+              size: 100
+            }
+          }
+        }
+      }
+      attr {
+        key: "shared_name"
+        value {
+          s: "dense/bias"
+        }
+      }
+    }
+    node {
+      name: "dense/bias/Read/ReadVariableOp"
+      op: "ReadVariableOp"
+      input: "dense/bias"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+              dim {
+                size: 100
+              }
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+    }
+    node {
+      name: "dense_1/kernel"
+      op: "VarHandleOp"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+            dim {
+              size: 100
+            }
+            dim {
+              size: 1
+            }
+          }
+        }
+      }
+      attr {
+        key: "shared_name"
+        value {
+          s: "dense_1/kernel"
+        }
+      }
+    }
+    node {
+      name: "dense_1/kernel/Read/ReadVariableOp"
+      op: "ReadVariableOp"
+      input: "dense_1/kernel"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+              dim {
+                size: 100
+              }
+              dim {
+                size: 1
+              }
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+    }
+    node {
+      name: "dense_1/bias"
+      op: "VarHandleOp"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+            dim {
+              size: 1
+            }
+          }
+        }
+      }
+      attr {
+        key: "shared_name"
+        value {
+          s: "dense_1/bias"
+        }
+      }
+    }
+    node {
+      name: "dense_1/bias/Read/ReadVariableOp"
+      op: "ReadVariableOp"
+      input: "dense_1/bias"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+              dim {
+                size: 1
+              }
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+    }
+    node {
+      name: "total"
+      op: "VarHandleOp"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+          }
+        }
+      }
+      attr {
+        key: "shared_name"
+        value {
+          s: "total"
+        }
+      }
+    }
+    node {
+      name: "total/Read/ReadVariableOp"
+      op: "ReadVariableOp"
+      input: "total"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+    }
+    node {
+      name: "count"
+      op: "VarHandleOp"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+          }
+        }
+      }
+      attr {
+        key: "shared_name"
+        value {
+          s: "count"
+        }
+      }
+    }
+    node {
+      name: "count/Read/ReadVariableOp"
+      op: "ReadVariableOp"
+      input: "count"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+    }
+    node {
+      name: "total_1"
+      op: "VarHandleOp"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+          }
+        }
+      }
+      attr {
+        key: "shared_name"
+        value {
+          s: "total_1"
+        }
+      }
+    }
+    node {
+      name: "total_1/Read/ReadVariableOp"
+      op: "ReadVariableOp"
+      input: "total_1"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+    }
+    node {
+      name: "count_1"
+      op: "VarHandleOp"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+          }
+        }
+      }
+      attr {
+        key: "shared_name"
+        value {
+          s: "count_1"
+        }
+      }
+    }
+    node {
+      name: "count_1/Read/ReadVariableOp"
+      op: "ReadVariableOp"
+      input: "count_1"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_FLOAT
+        }
+      }
+    }
+    node {
+      name: "NoOp"
+      op: "NoOp"
+    }
+    node {
+      name: "Const"
+      op: "Const"
+      device: "/device:CPU:0"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_STRING
+        }
+      }
+      attr {
+        key: "value"
+        value {
+          tensor {
+            dtype: DT_STRING
+            tensor_shape {
+            }
+            string_val: "\n\277\001\n\030\010\001\022\024layer_with_weights-0\n\013\010\001\022\007layer-0\n\030\010\002\022\024layer_with_weights-1\n\013\010\002\022\007layer-1\n\r\010\003\022\toptimizer\n\031\010\004\022\025regularization_losses\n\r\010\005\022\tvariables\n\027\010\006\022\023trainable_variables\n\r\010\007\022\tkeras_api\n\016\010\010\022\nsignatures\nh\n\n\010\t\022\006kernel\n\010\010\n\022\004bias\n\031\010\013\022\025regularization_losses\n\r\010\014\022\tvariables\n\027\010\r\022\023trainable_variables\n\r\010\016\022\tkeras_api\nh\n\n\010\017\022\006kernel\n\010\010\020\022\004bias\n\031\010\021\022\025regularization_losses\n\r\010\022\022\tvariables\n\027\010\023\022\023trainable_variables\n\r\010\024\022\tkeras_api\n\000\n\000\n\034\n\005\010\t\022\0010\n\005\010\n\022\0011\n\005\010\017\022\0012\n\005\010\020\022\0013\n\034\n\005\010\t\022\0010\n\005\010\n\022\0011\n\005\010\017\022\0012\n\005\010\020\022\0013\n\255\001\n\n\010\025\022\006layers\n\037\010\026\022\033layer_regularization_losses\n\033\010\027\022\027non_trainable_variables\n\021\010\030\022\rlayer_metrics\n\031\010\004\022\025regularization_losses\n\013\010\031\022\007metrics\n\r\010\005\022\tvariables\n\027\010\006\022\023trainable_variables\n\000\nX\022V\n\016VARIABLE_VALUE\022\014dense/kernel\0326layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE\nT\022R\n\016VARIABLE_VALUE\022\ndense/bias\0324layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010\t\022\0010\n\005\010\n\022\0011\n\016\n\005\010\t\022\0010\n\005\010\n\022\0011\n\255\001\n\n\010\032\022\006layers\n\037\010\033\022\033layer_regularization_losses\n\033\010\034\022\027non_trainable_variables\n\021\010\035\022\rlayer_metrics\n\031\010\013\022\025regularization_losses\n\013\010\036\022\007metrics\n\r\010\014\022\tvariables\n\027\010\r\022\023trainable_variables\nZ\022X\n\016VARIABLE_VALUE\022\016dense_1/kernel\0326layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE\nV\022T\n\016VARIABLE_VALUE\022\014dense_1/bias\0324layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010\017\022\0010\n\005\010\020\022\0011\n\016\n\005\010\017\022\0010\n\005\010\020\022\0011\n\255\001\n\n\010\037\022\006layers\n\037\010 \022\033layer_regularization_losses\n\033\010!\022\027non_trainable_variables\n\021\010\"\022\rlayer_metrics\n\031\010\021\022\025regularization_losses\n\013\010#\022\007metrics\n\r\010\022\022\tvariables\n\027\010\023\022\023trainable_variables\n\016\n\005\010\001\022\0010\n\005\010\002\022\0011\n\000\n\000\n\000\n\016\n\005\010$\022\0010\n\005\010%\022\0011\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n4\n\t\010&\022\005total\n\t\010\'\022\005count\n\r\010(\022\tvariables\n\r\010)\022\tkeras_api\nD\n\t\010*\022\005total\n\t\010+\022\005count\n\016\010,\022\n_fn_kwargs\n\r\010-\022\tvariables\n\r\010.\022\tkeras_api\nO\022M\n\016VARIABLE_VALUE\022\005total\0324keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE\nO\022M\n\016VARIABLE_VALUE\022\005count\0324keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE\n\016\n\005\010&\022\0010\n\005\010\'\022\0011\n\017\n\r\010(\022\tvariables\nQ\022O\n\016VARIABLE_VALUE\022\007total_1\0324keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE\nQ\022O\n\016VARIABLE_VALUE\022\007count_1\0324keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010*\022\0010\n\005\010+\022\0011\n\017\n\r\010-\022\tvariables"
+          }
+        }
+      }
+    }
+    node {
+      name: "serving_default_input_1"
+      op: "Placeholder"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+              dim {
+                size: -1
+              }
+              dim {
+                size: 214
+              }
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_INT32
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+            dim {
+              size: -1
+            }
+            dim {
+              size: 214
+            }
+          }
+        }
+      }
+    }
+    node {
+      name: "StatefulPartitionedCall"
+      op: "StatefulPartitionedCall"
+      input: "serving_default_input_1"
+      input: "dense/kernel"
+      input: "dense/bias"
+      input: "dense_1/kernel"
+      input: "dense_1/bias"
+      attr {
+        key: "Tin"
+        value {
+          list {
+            type: DT_INT32
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+          }
+        }
+      }
+      attr {
+        key: "Tout"
+        value {
+          list {
+            type: DT_FLOAT
+          }
+        }
+      }
+      attr {
+        key: "_collective_manager_ids"
+        value {
+          list {
+          }
+        }
+      }
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+              dim {
+                size: -1
+              }
+              dim {
+                size: 1
+              }
+            }
+          }
+        }
+      }
+      attr {
+        key: "_read_only_resource_inputs"
+        value {
+          list {
+            i: 1
+            i: 2
+            i: 3
+            i: 4
+          }
+        }
+      }
+      attr {
+        key: "config_proto"
+        value {
+          s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+        }
+      }
+      attr {
+        key: "f"
+        value {
+          func {
+            name: "__inference_signature_wrapper_6671"
+          }
+        }
+      }
+    }
+    node {
+      name: "saver_filename"
+      op: "Placeholder"
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "dtype"
+        value {
+          type: DT_STRING
+        }
+      }
+      attr {
+        key: "shape"
+        value {
+          shape {
+          }
+        }
+      }
+    }
+    node {
+      name: "StatefulPartitionedCall_1"
+      op: "StatefulPartitionedCall"
+      input: "saver_filename"
+      input: "dense/kernel/Read/ReadVariableOp"
+      input: "dense/bias/Read/ReadVariableOp"
+      input: "dense_1/kernel/Read/ReadVariableOp"
+      input: "dense_1/bias/Read/ReadVariableOp"
+      input: "total/Read/ReadVariableOp"
+      input: "count/Read/ReadVariableOp"
+      input: "total_1/Read/ReadVariableOp"
+      input: "count_1/Read/ReadVariableOp"
+      input: "Const"
+      attr {
+        key: "Tin"
+        value {
+          list {
+            type: DT_STRING
+            type: DT_FLOAT
+            type: DT_FLOAT
+            type: DT_FLOAT
+            type: DT_FLOAT
+            type: DT_FLOAT
+            type: DT_FLOAT
+            type: DT_FLOAT
+            type: DT_FLOAT
+            type: DT_STRING
+          }
+        }
+      }
+      attr {
+        key: "Tout"
+        value {
+          list {
+            type: DT_STRING
+          }
+        }
+      }
+      attr {
+        key: "_collective_manager_ids"
+        value {
+          list {
+          }
+        }
+      }
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "_read_only_resource_inputs"
+        value {
+          list {
+          }
+        }
+      }
+      attr {
+        key: "config_proto"
+        value {
+          s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+        }
+      }
+      attr {
+        key: "f"
+        value {
+          func {
+            name: "__inference__traced_save_6824"
+          }
+        }
+      }
+    }
+    node {
+      name: "StatefulPartitionedCall_2"
+      op: "StatefulPartitionedCall"
+      input: "saver_filename"
+      input: "dense/kernel"
+      input: "dense/bias"
+      input: "dense_1/kernel"
+      input: "dense_1/bias"
+      input: "total"
+      input: "count"
+      input: "total_1"
+      input: "count_1"
+      attr {
+        key: "Tin"
+        value {
+          list {
+            type: DT_STRING
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+            type: DT_RESOURCE
+          }
+        }
+      }
+      attr {
+        key: "Tout"
+        value {
+          list {
+            type: DT_STRING
+          }
+        }
+      }
+      attr {
+        key: "_collective_manager_ids"
+        value {
+          list {
+          }
+        }
+      }
+      attr {
+        key: "_output_shapes"
+        value {
+          list {
+            shape {
+            }
+          }
+        }
+      }
+      attr {
+        key: "_read_only_resource_inputs"
+        value {
+          list {
+          }
+        }
+      }
+      attr {
+        key: "config_proto"
+        value {
+          s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+        }
+      }
+      attr {
+        key: "f"
+        value {
+          func {
+            name: "__inference__traced_restore_6860"
+          }
+        }
+      }
+    }
+    library {
+      function {
+        signature {
+          name: "__inference__traced_restore_6860"
+          input_arg {
+            name: "file_prefix"
+            type: DT_STRING
+          }
+          input_arg {
+            name: "assignvariableop_dense_kernel"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "assignvariableop_1_dense_bias"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "assignvariableop_2_dense_1_kernel"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "assignvariableop_3_dense_1_bias"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "assignvariableop_4_total"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "assignvariableop_5_count"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "assignvariableop_6_total_1"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "assignvariableop_7_count_1"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity_9"
+            type: DT_STRING
+          }
+          is_stateful: true
+          control_output: "AssignVariableOp"
+          control_output: "AssignVariableOp_1"
+          control_output: "AssignVariableOp_2"
+          control_output: "AssignVariableOp_3"
+          control_output: "AssignVariableOp_4"
+          control_output: "AssignVariableOp_5"
+          control_output: "AssignVariableOp_6"
+          control_output: "AssignVariableOp_7"
+          control_output: "RestoreV2"
+          control_output: "RestoreV2_1"
+        }
+        node_def {
+          name: "RestoreV2/tensor_names"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 8
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                  dim {
+                    size: 8
+                  }
+                }
+                string_val: "layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "RestoreV2/tensor_names"
+          }
+        }
+        node_def {
+          name: "RestoreV2/shape_and_slices"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 8
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                  dim {
+                    size: 8
+                  }
+                }
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "RestoreV2/shape_and_slices"
+          }
+        }
+        node_def {
+          name: "RestoreV2"
+          op: "RestoreV2"
+          input: "file_prefix"
+          input: "RestoreV2/tensor_names:output:0"
+          input: "RestoreV2/shape_and_slices:output:0"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+                shape {
+                  unknown_rank: true
+                }
+                shape {
+                  unknown_rank: true
+                }
+                shape {
+                  unknown_rank: true
+                }
+                shape {
+                  unknown_rank: true
+                }
+                shape {
+                  unknown_rank: true
+                }
+                shape {
+                  unknown_rank: true
+                }
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtypes"
+            value {
+              list {
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "RestoreV2"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "RestoreV2:tensors:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        node_def {
+          name: "AssignVariableOp"
+          op: "AssignVariableOp"
+          input: "assignvariableop_dense_kernel"
+          input: "Identity:output:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "AssignVariableOp"
+          }
+        }
+        node_def {
+          name: "Identity_1"
+          op: "Identity"
+          input: "RestoreV2:tensors:1"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_1"
+          }
+        }
+        node_def {
+          name: "AssignVariableOp_1"
+          op: "AssignVariableOp"
+          input: "assignvariableop_1_dense_bias"
+          input: "Identity_1:output:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "AssignVariableOp_1"
+          }
+        }
+        node_def {
+          name: "Identity_2"
+          op: "Identity"
+          input: "RestoreV2:tensors:2"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_2"
+          }
+        }
+        node_def {
+          name: "AssignVariableOp_2"
+          op: "AssignVariableOp"
+          input: "assignvariableop_2_dense_1_kernel"
+          input: "Identity_2:output:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "AssignVariableOp_2"
+          }
+        }
+        node_def {
+          name: "Identity_3"
+          op: "Identity"
+          input: "RestoreV2:tensors:3"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_3"
+          }
+        }
+        node_def {
+          name: "AssignVariableOp_3"
+          op: "AssignVariableOp"
+          input: "assignvariableop_3_dense_1_bias"
+          input: "Identity_3:output:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "AssignVariableOp_3"
+          }
+        }
+        node_def {
+          name: "Identity_4"
+          op: "Identity"
+          input: "RestoreV2:tensors:4"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_4"
+          }
+        }
+        node_def {
+          name: "AssignVariableOp_4"
+          op: "AssignVariableOp"
+          input: "assignvariableop_4_total"
+          input: "Identity_4:output:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "AssignVariableOp_4"
+          }
+        }
+        node_def {
+          name: "Identity_5"
+          op: "Identity"
+          input: "RestoreV2:tensors:5"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_5"
+          }
+        }
+        node_def {
+          name: "AssignVariableOp_5"
+          op: "AssignVariableOp"
+          input: "assignvariableop_5_count"
+          input: "Identity_5:output:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "AssignVariableOp_5"
+          }
+        }
+        node_def {
+          name: "Identity_6"
+          op: "Identity"
+          input: "RestoreV2:tensors:6"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_6"
+          }
+        }
+        node_def {
+          name: "AssignVariableOp_6"
+          op: "AssignVariableOp"
+          input: "assignvariableop_6_total_1"
+          input: "Identity_6:output:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "AssignVariableOp_6"
+          }
+        }
+        node_def {
+          name: "Identity_7"
+          op: "Identity"
+          input: "RestoreV2:tensors:7"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_7"
+          }
+        }
+        node_def {
+          name: "AssignVariableOp_7"
+          op: "AssignVariableOp"
+          input: "assignvariableop_7_count_1"
+          input: "Identity_7:output:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "AssignVariableOp_7"
+          }
+        }
+        node_def {
+          name: "RestoreV2_1/tensor_names"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                  dim {
+                    size: 1
+                  }
+                }
+                string_val: "_CHECKPOINTABLE_OBJECT_GRAPH"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "RestoreV2_1/tensor_names"
+          }
+        }
+        node_def {
+          name: "RestoreV2_1/shape_and_slices"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                  dim {
+                    size: 1
+                  }
+                }
+                string_val: ""
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "RestoreV2_1/shape_and_slices"
+          }
+        }
+        node_def {
+          name: "RestoreV2_1"
+          op: "RestoreV2"
+          input: "file_prefix"
+          input: "RestoreV2_1/tensor_names:output:0"
+          input: "RestoreV2_1/shape_and_slices:output:0"
+          input: "^RestoreV2"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  unknown_rank: true
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtypes"
+            value {
+              list {
+                type: DT_STRING
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "RestoreV2_1"
+          }
+        }
+        node_def {
+          name: "NoOp"
+          op: "NoOp"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "NoOp"
+          }
+        }
+        node_def {
+          name: "Identity_8"
+          op: "Identity"
+          input: "file_prefix"
+          input: "^AssignVariableOp"
+          input: "^AssignVariableOp_1"
+          input: "^AssignVariableOp_2"
+          input: "^AssignVariableOp_3"
+          input: "^AssignVariableOp_4"
+          input: "^AssignVariableOp_5"
+          input: "^AssignVariableOp_6"
+          input: "^AssignVariableOp_7"
+          input: "^NoOp"
+          device: "/device:CPU:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_8"
+          }
+        }
+        node_def {
+          name: "Identity_9"
+          op: "Identity"
+          input: "Identity_8:output:0"
+          input: "^AssignVariableOp"
+          input: "^AssignVariableOp_1"
+          input: "^AssignVariableOp_2"
+          input: "^AssignVariableOp_3"
+          input: "^AssignVariableOp_4"
+          input: "^AssignVariableOp_5"
+          input: "^AssignVariableOp_6"
+          input: "^AssignVariableOp_7"
+          input: "^RestoreV2"
+          input: "^RestoreV2_1"
+          attr {
+            key: "T"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_9"
+          }
+        }
+        ret {
+          key: "identity_9"
+          value: "Identity_9:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "AssignVariableOp"
+          value: "AssignVariableOp"
+        }
+        control_ret {
+          key: "AssignVariableOp_1"
+          value: "AssignVariableOp_1"
+        }
+        control_ret {
+          key: "AssignVariableOp_2"
+          value: "AssignVariableOp_2"
+        }
+        control_ret {
+          key: "AssignVariableOp_3"
+          value: "AssignVariableOp_3"
+        }
+        control_ret {
+          key: "AssignVariableOp_4"
+          value: "AssignVariableOp_4"
+        }
+        control_ret {
+          key: "AssignVariableOp_5"
+          value: "AssignVariableOp_5"
+        }
+        control_ret {
+          key: "AssignVariableOp_6"
+          value: "AssignVariableOp_6"
+        }
+        control_ret {
+          key: "AssignVariableOp_7"
+          value: "AssignVariableOp_7"
+        }
+        control_ret {
+          key: "RestoreV2"
+          value: "RestoreV2"
+        }
+        control_ret {
+          key: "RestoreV2_1"
+          value: "RestoreV2_1"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "file_prefix"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 5
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 6
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 7
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 8
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_fn_6629"
+          input_arg {
+            name: "input_1"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "unknown"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_0"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_1"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_2"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "StatefulPartitionedCall"
+        }
+        node_def {
+          name: "StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "input_1"
+          input: "unknown"
+          input: "unknown_0"
+          input: "unknown_1"
+          input: "unknown_2"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+                i: 3
+                i: 4
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_sequential_layer_call_and_return_conditional_losses_6618"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "StatefulPartitionedCall:output:0"
+          input: "^StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "StatefulPartitionedCall"
+          value: "StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "input_1"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_and_return_conditional_losses_6587"
+          input_arg {
+            name: "input_1"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "dense_6555"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_6557"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_6581"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_6583"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "dense/StatefulPartitionedCall"
+          control_output: "dense_1/StatefulPartitionedCall"
+        }
+        node_def {
+          name: "dense/StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "input_1"
+          input: "dense_6555"
+          input: "dense_6557"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_layer_call_and_return_conditional_losses_6544"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "dense_1/StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "dense/StatefulPartitionedCall:output:0"
+          input: "dense_1_6581"
+          input: "dense_1_6583"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_FLOAT
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "dense_1/StatefulPartitionedCall:output:0"
+          input: "^dense/StatefulPartitionedCall"
+          input: "^dense_1/StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "dense/StatefulPartitionedCall"
+          value: "dense/StatefulPartitionedCall"
+        }
+        control_ret {
+          key: "dense_1/StatefulPartitionedCall"
+          value: "dense_1/StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "input_1"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_and_return_conditional_losses_6618"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "dense_6607"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_6609"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_6612"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_6614"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "dense/StatefulPartitionedCall"
+          control_output: "dense_1/StatefulPartitionedCall"
+        }
+        node_def {
+          name: "dense/StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "inputs"
+          input: "dense_6607"
+          input: "dense_6609"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_layer_call_and_return_conditional_losses_6544"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "dense_1/StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "dense/StatefulPartitionedCall:output:0"
+          input: "dense_1_6612"
+          input: "dense_1_6614"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_FLOAT
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "dense_1/StatefulPartitionedCall:output:0"
+          input: "^dense/StatefulPartitionedCall"
+          input: "^dense_1/StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "dense/StatefulPartitionedCall"
+          value: "dense/StatefulPartitionedCall"
+        }
+        control_ret {
+          key: "dense_1/StatefulPartitionedCall"
+          value: "dense_1/StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_fn_6656"
+          input_arg {
+            name: "input_1"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "unknown"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_0"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_1"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_2"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "StatefulPartitionedCall"
+        }
+        node_def {
+          name: "StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "input_1"
+          input: "unknown"
+          input: "unknown_0"
+          input: "unknown_1"
+          input: "unknown_2"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+                i: 3
+                i: 4
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_sequential_layer_call_and_return_conditional_losses_6645"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "StatefulPartitionedCall:output:0"
+          input: "^StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "StatefulPartitionedCall"
+          value: "StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "input_1"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_dense_1_layer_call_and_return_conditional_losses_6764"
+          input_arg {
+            name: "inputs"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+        }
+        node_def {
+          name: "MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "MatMul"
+          op: "MatMul"
+          input: "inputs"
+          input: "MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MatMul"
+          }
+        }
+        node_def {
+          name: "BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "BiasAdd"
+          op: "BiasAdd"
+          input: "MatMul:product:0"
+          input: "BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "BiasAdd"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 100
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 100
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_dense_layer_call_fn_6754"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "unknown"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_0"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "StatefulPartitionedCall"
+        }
+        node_def {
+          name: "StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "inputs"
+          input: "unknown"
+          input: "unknown_0"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_layer_call_and_return_conditional_losses_6544"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "StatefulPartitionedCall:output:0"
+          input: "^StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "StatefulPartitionedCall"
+          value: "StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference__traced_save_6824"
+          input_arg {
+            name: "file_prefix"
+            type: DT_STRING
+          }
+          input_arg {
+            name: "savev2_dense_kernel_read_readvariableop"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "savev2_dense_bias_read_readvariableop"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "savev2_dense_1_kernel_read_readvariableop"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "savev2_dense_1_bias_read_readvariableop"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "savev2_total_read_readvariableop"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "savev2_count_read_readvariableop"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "savev2_total_1_read_readvariableop"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "savev2_count_1_read_readvariableop"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "savev2_1_const"
+            type: DT_STRING
+          }
+          output_arg {
+            name: "identity_1"
+            type: DT_STRING
+          }
+          is_stateful: true
+          control_output: "MergeV2Checkpoints"
+          control_output: "SaveV2"
+          control_output: "SaveV2_1"
+        }
+        node_def {
+          name: "StaticRegexFullMatch"
+          op: "StaticRegexFullMatch"
+          input: "file_prefix"
+          device: "/device:CPU:*"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          attr {
+            key: "pattern"
+            value {
+              s: "^s3://.*"
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StaticRegexFullMatch"
+          }
+        }
+        node_def {
+          name: "Const"
+          op: "Const"
+          device: "/device:CPU:*"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                }
+                string_val: ".part"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Const"
+          }
+        }
+        node_def {
+          name: "Const_1"
+          op: "Const"
+          device: "/device:CPU:*"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                }
+                string_val: "_temp_6f1e5fef49bb4c06ace07a8a95dfbb1b/part"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Const_1"
+          }
+        }
+        node_def {
+          name: "Select"
+          op: "Select"
+          input: "StaticRegexFullMatch:output:0"
+          input: "Const:output:0"
+          input: "Const_1:output:0"
+          device: "/device:CPU:*"
+          attr {
+            key: "T"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Select"
+          }
+        }
+        node_def {
+          name: "StringJoin"
+          op: "StringJoin"
+          input: "file_prefix"
+          input: "Select:output:0"
+          device: "/device:CPU:*"
+          attr {
+            key: "N"
+            value {
+              i: 2
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StringJoin"
+          }
+        }
+        node_def {
+          name: "num_shards"
+          op: "Const"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_INT32
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_INT32
+                tensor_shape {
+                }
+                int_val: 2
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "num_shards"
+          }
+        }
+        node_def {
+          name: "ShardedFilename/shard"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_INT32
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_INT32
+                tensor_shape {
+                }
+                int_val: 0
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "ShardedFilename/shard"
+          }
+        }
+        node_def {
+          name: "ShardedFilename"
+          op: "ShardedFilename"
+          input: "StringJoin:output:0"
+          input: "ShardedFilename/shard:output:0"
+          input: "num_shards:output:0"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "ShardedFilename"
+          }
+        }
+        node_def {
+          name: "SaveV2/tensor_names"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 8
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                  dim {
+                    size: 8
+                  }
+                }
+                string_val: "layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE"
+                string_val: "keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "SaveV2/tensor_names"
+          }
+        }
+        node_def {
+          name: "SaveV2/shape_and_slices"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 8
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                  dim {
+                    size: 8
+                  }
+                }
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+                string_val: ""
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "SaveV2/shape_and_slices"
+          }
+        }
+        node_def {
+          name: "SaveV2"
+          op: "SaveV2"
+          input: "ShardedFilename:filename:0"
+          input: "SaveV2/tensor_names:output:0"
+          input: "SaveV2/shape_and_slices:output:0"
+          input: "savev2_dense_kernel_read_readvariableop"
+          input: "savev2_dense_bias_read_readvariableop"
+          input: "savev2_dense_1_kernel_read_readvariableop"
+          input: "savev2_dense_1_bias_read_readvariableop"
+          input: "savev2_total_read_readvariableop"
+          input: "savev2_count_read_readvariableop"
+          input: "savev2_total_1_read_readvariableop"
+          input: "savev2_count_1_read_readvariableop"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtypes"
+            value {
+              list {
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+                type: DT_FLOAT
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "SaveV2"
+          }
+        }
+        node_def {
+          name: "ShardedFilename_1/shard"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_INT32
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_INT32
+                tensor_shape {
+                }
+                int_val: 1
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "ShardedFilename_1/shard"
+          }
+        }
+        node_def {
+          name: "ShardedFilename_1"
+          op: "ShardedFilename"
+          input: "StringJoin:output:0"
+          input: "ShardedFilename_1/shard:output:0"
+          input: "num_shards:output:0"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "ShardedFilename_1"
+          }
+        }
+        node_def {
+          name: "SaveV2_1/tensor_names"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                  dim {
+                    size: 1
+                  }
+                }
+                string_val: "_CHECKPOINTABLE_OBJECT_GRAPH"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "SaveV2_1/tensor_names"
+          }
+        }
+        node_def {
+          name: "SaveV2_1/shape_and_slices"
+          op: "Const"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "value"
+            value {
+              tensor {
+                dtype: DT_STRING
+                tensor_shape {
+                  dim {
+                    size: 1
+                  }
+                }
+                string_val: ""
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "SaveV2_1/shape_and_slices"
+          }
+        }
+        node_def {
+          name: "SaveV2_1"
+          op: "SaveV2"
+          input: "ShardedFilename_1:filename:0"
+          input: "SaveV2_1/tensor_names:output:0"
+          input: "SaveV2_1/shape_and_slices:output:0"
+          input: "savev2_1_const"
+          input: "^SaveV2"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "dtypes"
+            value {
+              list {
+                type: DT_STRING
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "SaveV2_1"
+          }
+        }
+        node_def {
+          name: "MergeV2Checkpoints/checkpoint_prefixes"
+          op: "Pack"
+          input: "ShardedFilename:filename:0"
+          input: "ShardedFilename_1:filename:0"
+          input: "^SaveV2"
+          input: "^SaveV2_1"
+          device: "/device:CPU:0"
+          attr {
+            key: "N"
+            value {
+              i: 2
+            }
+          }
+          attr {
+            key: "T"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 2
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MergeV2Checkpoints/checkpoint_prefixes"
+          }
+        }
+        node_def {
+          name: "MergeV2Checkpoints"
+          op: "MergeV2Checkpoints"
+          input: "MergeV2Checkpoints/checkpoint_prefixes:output:0"
+          input: "file_prefix"
+          input: "^SaveV2_1"
+          device: "/device:CPU:0"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MergeV2Checkpoints"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "file_prefix"
+          input: "^MergeV2Checkpoints"
+          device: "/device:CPU:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        node_def {
+          name: "Identity_1"
+          op: "Identity"
+          input: "Identity:output:0"
+          input: "^MergeV2Checkpoints"
+          input: "^SaveV2"
+          input: "^SaveV2_1"
+          attr {
+            key: "T"
+            value {
+              type: DT_STRING
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity_1"
+          }
+        }
+        ret {
+          key: "identity_1"
+          value: "Identity_1:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+              }
+              shape {
+                dim {
+                  size: 214
+                }
+                dim {
+                  size: 100
+                }
+              }
+              shape {
+                dim {
+                  size: 100
+                }
+              }
+              shape {
+                dim {
+                  size: 100
+                }
+                dim {
+                  size: 1
+                }
+              }
+              shape {
+                dim {
+                  size: 1
+                }
+              }
+              shape {
+              }
+              shape {
+              }
+              shape {
+              }
+              shape {
+              }
+              shape {
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "MergeV2Checkpoints"
+          value: "MergeV2Checkpoints"
+        }
+        control_ret {
+          key: "SaveV2"
+          value: "SaveV2"
+        }
+        control_ret {
+          key: "SaveV2_1"
+          value: "SaveV2_1"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "file_prefix"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: 214
+                    }
+                    dim {
+                      size: 100
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: 100
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: 100
+                    }
+                    dim {
+                      size: 1
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: 1
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 5
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 6
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 7
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 8
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 9
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_and_return_conditional_losses_6689"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "dense_matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+        }
+        node_def {
+          name: "dense/Cast"
+          op: "Cast"
+          input: "inputs"
+          attr {
+            key: "DstT"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "SrcT"
+            value {
+              type: DT_INT32
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 214
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/Cast"
+          }
+        }
+        node_def {
+          name: "dense/MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "dense_matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 214
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "dense/MatMul"
+          op: "MatMul"
+          input: "dense/Cast:y:0"
+          input: "dense/MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/MatMul"
+          }
+        }
+        node_def {
+          name: "dense/BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "dense_biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "dense/BiasAdd"
+          op: "BiasAdd"
+          input: "dense/MatMul:product:0"
+          input: "dense/BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/BiasAdd"
+          }
+        }
+        node_def {
+          name: "dense/Relu"
+          op: "Relu"
+          input: "dense/BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/Relu"
+          }
+        }
+        node_def {
+          name: "dense_1/MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "dense_1_matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "dense_1/MatMul"
+          op: "MatMul"
+          input: "dense/Relu:activations:0"
+          input: "dense_1/MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/MatMul"
+          }
+        }
+        node_def {
+          name: "dense_1/BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "dense_1_biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "dense_1/BiasAdd"
+          op: "BiasAdd"
+          input: "dense_1/MatMul:product:0"
+          input: "dense_1/BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/BiasAdd"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "dense_1/BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_dense_layer_call_and_return_conditional_losses_6745"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+        }
+        node_def {
+          name: "Cast"
+          op: "Cast"
+          input: "inputs"
+          attr {
+            key: "DstT"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "SrcT"
+            value {
+              type: DT_INT32
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 214
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Cast"
+          }
+        }
+        node_def {
+          name: "MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 214
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "MatMul"
+          op: "MatMul"
+          input: "Cast:y:0"
+          input: "MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MatMul"
+          }
+        }
+        node_def {
+          name: "BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "BiasAdd"
+          op: "BiasAdd"
+          input: "MatMul:product:0"
+          input: "BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "BiasAdd"
+          }
+        }
+        node_def {
+          name: "Relu"
+          op: "Relu"
+          input: "BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Relu"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "Relu:activations:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_dense_1_layer_call_fn_6773"
+          input_arg {
+            name: "inputs"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "unknown"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_0"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "StatefulPartitionedCall"
+        }
+        node_def {
+          name: "StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "inputs"
+          input: "unknown"
+          input: "unknown_0"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_FLOAT
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "StatefulPartitionedCall:output:0"
+          input: "^StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 100
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "StatefulPartitionedCall"
+          value: "StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 100
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference__wrapped_model_6528"
+          input_arg {
+            name: "input_1"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "sequential_dense_matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "sequential_dense_biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "sequential_dense_1_matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "sequential_dense_1_biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+        }
+        node_def {
+          name: "sequential/dense/Cast"
+          op: "Cast"
+          input: "input_1"
+          attr {
+            key: "DstT"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "SrcT"
+            value {
+              type: DT_INT32
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 214
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense/Cast"
+          }
+        }
+        node_def {
+          name: "sequential/dense/MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "sequential_dense_matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 214
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense/MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "sequential/dense/MatMul"
+          op: "MatMul"
+          input: "sequential/dense/Cast:y:0"
+          input: "sequential/dense/MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense/MatMul"
+          }
+        }
+        node_def {
+          name: "sequential/dense/BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "sequential_dense_biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense/BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "sequential/dense/BiasAdd"
+          op: "BiasAdd"
+          input: "sequential/dense/MatMul:product:0"
+          input: "sequential/dense/BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense/BiasAdd"
+          }
+        }
+        node_def {
+          name: "sequential/dense/Relu"
+          op: "Relu"
+          input: "sequential/dense/BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense/Relu"
+          }
+        }
+        node_def {
+          name: "sequential/dense_1/MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "sequential_dense_1_matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense_1/MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "sequential/dense_1/MatMul"
+          op: "MatMul"
+          input: "sequential/dense/Relu:activations:0"
+          input: "sequential/dense_1/MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense_1/MatMul"
+          }
+        }
+        node_def {
+          name: "sequential/dense_1/BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "sequential_dense_1_biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense_1/BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "sequential/dense_1/BiasAdd"
+          op: "BiasAdd"
+          input: "sequential/dense_1/MatMul:product:0"
+          input: "sequential/dense_1/BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "sequential/dense_1/BiasAdd"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "sequential/dense_1/BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "input_1"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_dense_layer_call_and_return_conditional_losses_6544"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+        }
+        node_def {
+          name: "Cast"
+          op: "Cast"
+          input: "inputs"
+          attr {
+            key: "DstT"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "SrcT"
+            value {
+              type: DT_INT32
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 214
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Cast"
+          }
+        }
+        node_def {
+          name: "MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 214
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "MatMul"
+          op: "MatMul"
+          input: "Cast:y:0"
+          input: "MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MatMul"
+          }
+        }
+        node_def {
+          name: "BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "BiasAdd"
+          op: "BiasAdd"
+          input: "MatMul:product:0"
+          input: "BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "BiasAdd"
+          }
+        }
+        node_def {
+          name: "Relu"
+          op: "Relu"
+          input: "BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Relu"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "Relu:activations:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_and_return_conditional_losses_6601"
+          input_arg {
+            name: "input_1"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "dense_6590"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_6592"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_6595"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_6597"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "dense/StatefulPartitionedCall"
+          control_output: "dense_1/StatefulPartitionedCall"
+        }
+        node_def {
+          name: "dense/StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "input_1"
+          input: "dense_6590"
+          input: "dense_6592"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_layer_call_and_return_conditional_losses_6544"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "dense_1/StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "dense/StatefulPartitionedCall:output:0"
+          input: "dense_1_6595"
+          input: "dense_1_6597"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_FLOAT
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "dense_1/StatefulPartitionedCall:output:0"
+          input: "^dense/StatefulPartitionedCall"
+          input: "^dense_1/StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "dense/StatefulPartitionedCall"
+          value: "dense/StatefulPartitionedCall"
+        }
+        control_ret {
+          key: "dense_1/StatefulPartitionedCall"
+          value: "dense_1/StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "input_1"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_fn_6733"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "unknown"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_0"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_1"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_2"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "StatefulPartitionedCall"
+        }
+        node_def {
+          name: "StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "inputs"
+          input: "unknown"
+          input: "unknown_0"
+          input: "unknown_1"
+          input: "unknown_2"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+                i: 3
+                i: 4
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_sequential_layer_call_and_return_conditional_losses_6645"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "StatefulPartitionedCall:output:0"
+          input: "^StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "StatefulPartitionedCall"
+          value: "StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_and_return_conditional_losses_6645"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "dense_6634"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_6636"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_6639"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_6641"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "dense/StatefulPartitionedCall"
+          control_output: "dense_1/StatefulPartitionedCall"
+        }
+        node_def {
+          name: "dense/StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "inputs"
+          input: "dense_6634"
+          input: "dense_6636"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_layer_call_and_return_conditional_losses_6544"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "dense_1/StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "dense/StatefulPartitionedCall:output:0"
+          input: "dense_1_6639"
+          input: "dense_1_6641"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_FLOAT
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "dense_1/StatefulPartitionedCall:output:0"
+          input: "^dense/StatefulPartitionedCall"
+          input: "^dense_1/StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "dense/StatefulPartitionedCall"
+          value: "dense/StatefulPartitionedCall"
+        }
+        control_ret {
+          key: "dense_1/StatefulPartitionedCall"
+          value: "dense_1/StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570"
+          input_arg {
+            name: "inputs"
+            type: DT_FLOAT
+          }
+          input_arg {
+            name: "matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+        }
+        node_def {
+          name: "MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "MatMul"
+          op: "MatMul"
+          input: "inputs"
+          input: "MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "MatMul"
+          }
+        }
+        node_def {
+          name: "BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "BiasAdd"
+          op: "BiasAdd"
+          input: "MatMul:product:0"
+          input: "BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "BiasAdd"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 100
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 100
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_signature_wrapper_6671"
+          input_arg {
+            name: "input_1"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "unknown"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_0"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_1"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_2"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "StatefulPartitionedCall"
+        }
+        node_def {
+          name: "StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "input_1"
+          input: "unknown"
+          input: "unknown_0"
+          input: "unknown_1"
+          input: "unknown_2"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+                i: 3
+                i: 4
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference__wrapped_model_6528"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "StatefulPartitionedCall:output:0"
+          input: "^StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "StatefulPartitionedCall"
+          value: "StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "input_1"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_fn_6720"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "unknown"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_0"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_1"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "unknown_2"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+          control_output: "StatefulPartitionedCall"
+        }
+        node_def {
+          name: "StatefulPartitionedCall"
+          op: "StatefulPartitionedCall"
+          input: "inputs"
+          input: "unknown"
+          input: "unknown_0"
+          input: "unknown_1"
+          input: "unknown_2"
+          attr {
+            key: "Tin"
+            value {
+              list {
+                type: DT_INT32
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+                type: DT_RESOURCE
+              }
+            }
+          }
+          attr {
+            key: "Tout"
+            value {
+              list {
+                type: DT_FLOAT
+              }
+            }
+          }
+          attr {
+            key: "_collective_manager_ids"
+            value {
+              list {
+              }
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "_read_only_resource_inputs"
+            value {
+              list {
+                i: 1
+                i: 2
+                i: 3
+                i: 4
+              }
+            }
+          }
+          attr {
+            key: "config_proto"
+            value {
+              s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001"
+            }
+          }
+          attr {
+            key: "f"
+            value {
+              func {
+                name: "__inference_sequential_layer_call_and_return_conditional_losses_6618"
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "StatefulPartitionedCall"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "StatefulPartitionedCall:output:0"
+          input: "^StatefulPartitionedCall"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        control_ret {
+          key: "StatefulPartitionedCall"
+          value: "StatefulPartitionedCall"
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+      function {
+        signature {
+          name: "__inference_sequential_layer_call_and_return_conditional_losses_6707"
+          input_arg {
+            name: "inputs"
+            type: DT_INT32
+          }
+          input_arg {
+            name: "dense_matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_matmul_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          input_arg {
+            name: "dense_1_biasadd_readvariableop_resource"
+            type: DT_RESOURCE
+          }
+          output_arg {
+            name: "identity"
+            type: DT_FLOAT
+          }
+          is_stateful: true
+        }
+        node_def {
+          name: "dense/Cast"
+          op: "Cast"
+          input: "inputs"
+          attr {
+            key: "DstT"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "SrcT"
+            value {
+              type: DT_INT32
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 214
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/Cast"
+          }
+        }
+        node_def {
+          name: "dense/MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "dense_matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 214
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "dense/MatMul"
+          op: "MatMul"
+          input: "dense/Cast:y:0"
+          input: "dense/MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/MatMul"
+          }
+        }
+        node_def {
+          name: "dense/BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "dense_biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "dense/BiasAdd"
+          op: "BiasAdd"
+          input: "dense/MatMul:product:0"
+          input: "dense/BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/BiasAdd"
+          }
+        }
+        node_def {
+          name: "dense/Relu"
+          op: "Relu"
+          input: "dense/BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense/Relu"
+          }
+        }
+        node_def {
+          name: "dense_1/MatMul/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "dense_1_matmul_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 100
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/MatMul/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "dense_1/MatMul"
+          op: "MatMul"
+          input: "dense/Relu:activations:0"
+          input: "dense_1/MatMul/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/MatMul"
+          }
+        }
+        node_def {
+          name: "dense_1/BiasAdd/ReadVariableOp"
+          op: "ReadVariableOp"
+          input: "dense_1_biasadd_readvariableop_resource"
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          attr {
+            key: "dtype"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/BiasAdd/ReadVariableOp"
+          }
+        }
+        node_def {
+          name: "dense_1/BiasAdd"
+          op: "BiasAdd"
+          input: "dense_1/MatMul:product:0"
+          input: "dense_1/BiasAdd/ReadVariableOp:value:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "dense_1/BiasAdd"
+          }
+        }
+        node_def {
+          name: "Identity"
+          op: "Identity"
+          input: "dense_1/BiasAdd:output:0"
+          attr {
+            key: "T"
+            value {
+              type: DT_FLOAT
+            }
+          }
+          attr {
+            key: "_output_shapes"
+            value {
+              list {
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+              }
+            }
+          }
+          experimental_debug_info {
+            original_node_names: "Identity"
+          }
+        }
+        ret {
+          key: "identity"
+          value: "Identity:output:0"
+        }
+        attr {
+          key: "_input_shapes"
+          value {
+            list {
+              shape {
+                dim {
+                  size: -1
+                }
+                dim {
+                  size: 214
+                }
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+              shape {
+                unknown_rank: true
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 0
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                }
+              }
+            }
+            attr {
+              key: "_user_specified_name"
+              value {
+                s: "inputs"
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 1
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 2
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 3
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+        arg_attr {
+          key: 4
+          value {
+            attr {
+              key: "_output_shapes"
+              value {
+                list {
+                  shape {
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    versions {
+      producer: 331
+      min_consumer: 12
+    }
+  }
+  saver_def {
+    filename_tensor_name: "saver_filename:0"
+    save_tensor_name: "StatefulPartitionedCall_1:0"
+    restore_op_name: "StatefulPartitionedCall_2"
+    version: V2
+  }
+  collection_def {
+    key: "saved_model_main_op"
+    value {
+      node_list {
+        value: "NoOp"
+      }
+    }
+  }
+  signature_def {
+    key: "__saved_model_init_op"
+    value {
+      outputs {
+        key: "__saved_model_init_op"
+        value {
+          name: "NoOp"
+          tensor_shape {
+            unknown_rank: true
+          }
+        }
+      }
+    }
+  }
+  signature_def {
+    key: "serving_default"
+    value {
+      inputs {
+        key: "input_1"
+        value {
+          name: "serving_default_input_1:0"
+          dtype: DT_INT32
+          tensor_shape {
+            dim {
+              size: -1
+            }
+            dim {
+              size: 214
+            }
+          }
+        }
+      }
+      outputs {
+        key: "output_1"
+        value {
+          name: "StatefulPartitionedCall:0"
+          dtype: DT_FLOAT
+          tensor_shape {
+            dim {
+              size: -1
+            }
+            dim {
+              size: 1
+            }
+          }
+        }
+      }
+      method_name: "tensorflow/serving/predict"
+    }
+  }
+  object_graph_def {
+    nodes {
+      children {
+        node_id: 1
+        local_name: "layer_with_weights-0"
+      }
+      children {
+        node_id: 1
+        local_name: "layer-0"
+      }
+      children {
+        node_id: 2
+        local_name: "layer_with_weights-1"
+      }
+      children {
+        node_id: 2
+        local_name: "layer-1"
+      }
+      children {
+        node_id: 3
+        local_name: "optimizer"
+      }
+      children {
+        node_id: 4
+        local_name: "regularization_losses"
+      }
+      children {
+        node_id: 5
+        local_name: "variables"
+      }
+      children {
+        node_id: 6
+        local_name: "trainable_variables"
+      }
+      children {
+        node_id: 7
+        local_name: "keras_api"
+      }
+      children {
+        node_id: 8
+        local_name: "signatures"
+      }
+      children {
+        node_id: 47
+        local_name: "__call__"
+      }
+      children {
+        node_id: 48
+        local_name: "_default_save_signature"
+      }
+      children {
+        node_id: 49
+        local_name: "call_and_return_all_conditional_losses"
+      }
+      user_object {
+        identifier: "_tf_keras_sequential"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+        metadata: "{\"class_name\": \"Sequential\", \"name\": \"sequential\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"config\": {\"name\": \"sequential\", \"layers\": [{\"class_name\": \"Dense\", \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}, {\"class_name\": \"Dense\", \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}], \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 214}}}, \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}, \"is_graph_network\": false, \"keras_version\": \"2.2.4-tf\", \"backend\": \"tensorflow\", \"model_config\": {\"class_name\": \"Sequential\", \"config\": {\"name\": \"sequential\", \"layers\": [{\"class_name\": \"Dense\", \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}, {\"class_name\": \"Dense\", \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}], \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}}}, \"training_config\": {\"loss\": \"mean_absolute_error\", \"metrics\": [\"mean_squared_error\"], \"weighted_metrics\": null, \"loss_weights\": null, \"sample_weight_mode\": null, \"optimizer_config\": {\"class_name\": \"Adam\", \"config\": {\"name\": \"Adam\", \"learning_rate\": 0.0003000000142492354, \"decay\": 0.0, \"beta_1\": 0.8999999761581421, \"beta_2\": 0.9990000128746033, \"epsilon\": 1e-07, \"amsgrad\": false}}}}"
+      }
+    }
+    nodes {
+      children {
+        node_id: 9
+        local_name: "kernel"
+      }
+      children {
+        node_id: 10
+        local_name: "bias"
+      }
+      children {
+        node_id: 11
+        local_name: "regularization_losses"
+      }
+      children {
+        node_id: 12
+        local_name: "variables"
+      }
+      children {
+        node_id: 13
+        local_name: "trainable_variables"
+      }
+      children {
+        node_id: 14
+        local_name: "keras_api"
+      }
+      children {
+        node_id: 50
+        local_name: "__call__"
+      }
+      children {
+        node_id: 51
+        local_name: "call_and_return_all_conditional_losses"
+      }
+      user_object {
+        identifier: "_tf_keras_layer"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+        metadata: "{\"class_name\": \"Dense\", \"name\": \"dense\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 214}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [null, 214]}}"
+      }
+    }
+    nodes {
+      children {
+        node_id: 15
+        local_name: "kernel"
+      }
+      children {
+        node_id: 16
+        local_name: "bias"
+      }
+      children {
+        node_id: 17
+        local_name: "regularization_losses"
+      }
+      children {
+        node_id: 18
+        local_name: "variables"
+      }
+      children {
+        node_id: 19
+        local_name: "trainable_variables"
+      }
+      children {
+        node_id: 20
+        local_name: "keras_api"
+      }
+      children {
+        node_id: 52
+        local_name: "__call__"
+      }
+      children {
+        node_id: 53
+        local_name: "call_and_return_all_conditional_losses"
+      }
+      user_object {
+        identifier: "_tf_keras_layer"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+        metadata: "{\"class_name\": \"Dense\", \"name\": \"dense_1\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 100}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [null, 100]}}"
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "optimizer"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 9
+        local_name: "0"
+      }
+      children {
+        node_id: 10
+        local_name: "1"
+      }
+      children {
+        node_id: 15
+        local_name: "2"
+      }
+      children {
+        node_id: 16
+        local_name: "3"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 9
+        local_name: "0"
+      }
+      children {
+        node_id: 10
+        local_name: "1"
+      }
+      children {
+        node_id: 15
+        local_name: "2"
+      }
+      children {
+        node_id: 16
+        local_name: "3"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 21
+        local_name: "layers"
+      }
+      children {
+        node_id: 22
+        local_name: "layer_regularization_losses"
+      }
+      children {
+        node_id: 23
+        local_name: "non_trainable_variables"
+      }
+      children {
+        node_id: 24
+        local_name: "layer_metrics"
+      }
+      children {
+        node_id: 4
+        local_name: "regularization_losses"
+      }
+      children {
+        node_id: 25
+        local_name: "metrics"
+      }
+      children {
+        node_id: 5
+        local_name: "variables"
+      }
+      children {
+        node_id: 6
+        local_name: "trainable_variables"
+      }
+      children {
+        node_id: 47
+        local_name: "__call__"
+      }
+      children {
+        node_id: 48
+        local_name: "_default_save_signature"
+      }
+      children {
+        node_id: 49
+        local_name: "call_and_return_all_conditional_losses"
+      }
+      children {
+        node_id: 49
+        local_name: "call_and_return_conditional_losses"
+      }
+      user_object {
+        identifier: "_generic_user_object"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 54
+        local_name: "serving_default"
+      }
+      user_object {
+        identifier: "signature_map"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      variable {
+        dtype: DT_FLOAT
+        shape {
+          dim {
+            size: 214
+          }
+          dim {
+            size: 100
+          }
+        }
+        trainable: true
+        name: "dense/kernel"
+      }
+    }
+    nodes {
+      variable {
+        dtype: DT_FLOAT
+        shape {
+          dim {
+            size: 100
+          }
+        }
+        trainable: true
+        name: "dense/bias"
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 9
+        local_name: "0"
+      }
+      children {
+        node_id: 10
+        local_name: "1"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 9
+        local_name: "0"
+      }
+      children {
+        node_id: 10
+        local_name: "1"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 26
+        local_name: "layers"
+      }
+      children {
+        node_id: 27
+        local_name: "layer_regularization_losses"
+      }
+      children {
+        node_id: 28
+        local_name: "non_trainable_variables"
+      }
+      children {
+        node_id: 29
+        local_name: "layer_metrics"
+      }
+      children {
+        node_id: 11
+        local_name: "regularization_losses"
+      }
+      children {
+        node_id: 30
+        local_name: "metrics"
+      }
+      children {
+        node_id: 12
+        local_name: "variables"
+      }
+      children {
+        node_id: 13
+        local_name: "trainable_variables"
+      }
+      children {
+        node_id: 50
+        local_name: "__call__"
+      }
+      children {
+        node_id: 51
+        local_name: "call_and_return_all_conditional_losses"
+      }
+      children {
+        node_id: 51
+        local_name: "call_and_return_conditional_losses"
+      }
+      user_object {
+        identifier: "_generic_user_object"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      variable {
+        dtype: DT_FLOAT
+        shape {
+          dim {
+            size: 100
+          }
+          dim {
+            size: 1
+          }
+        }
+        trainable: true
+        name: "dense_1/kernel"
+      }
+    }
+    nodes {
+      variable {
+        dtype: DT_FLOAT
+        shape {
+          dim {
+            size: 1
+          }
+        }
+        trainable: true
+        name: "dense_1/bias"
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 15
+        local_name: "0"
+      }
+      children {
+        node_id: 16
+        local_name: "1"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 15
+        local_name: "0"
+      }
+      children {
+        node_id: 16
+        local_name: "1"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 31
+        local_name: "layers"
+      }
+      children {
+        node_id: 32
+        local_name: "layer_regularization_losses"
+      }
+      children {
+        node_id: 33
+        local_name: "non_trainable_variables"
+      }
+      children {
+        node_id: 34
+        local_name: "layer_metrics"
+      }
+      children {
+        node_id: 17
+        local_name: "regularization_losses"
+      }
+      children {
+        node_id: 35
+        local_name: "metrics"
+      }
+      children {
+        node_id: 18
+        local_name: "variables"
+      }
+      children {
+        node_id: 19
+        local_name: "trainable_variables"
+      }
+      children {
+        node_id: 52
+        local_name: "__call__"
+      }
+      children {
+        node_id: 53
+        local_name: "call_and_return_all_conditional_losses"
+      }
+      children {
+        node_id: 53
+        local_name: "call_and_return_conditional_losses"
+      }
+      user_object {
+        identifier: "_generic_user_object"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 1
+        local_name: "0"
+      }
+      children {
+        node_id: 2
+        local_name: "1"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_dict_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 36
+        local_name: "0"
+      }
+      children {
+        node_id: 37
+        local_name: "1"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_dict_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_dict_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 38
+        local_name: "total"
+      }
+      children {
+        node_id: 39
+        local_name: "count"
+      }
+      children {
+        node_id: 40
+        local_name: "variables"
+      }
+      children {
+        node_id: 41
+        local_name: "keras_api"
+      }
+      user_object {
+        identifier: "_tf_keras_metric"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+        metadata: "{\"class_name\": \"Mean\", \"name\": \"loss\", \"dtype\": \"float32\", \"config\": {\"name\": \"loss\", \"dtype\": \"float32\"}}"
+      }
+    }
+    nodes {
+      children {
+        node_id: 42
+        local_name: "total"
+      }
+      children {
+        node_id: 43
+        local_name: "count"
+      }
+      children {
+        node_id: 44
+        local_name: "_fn_kwargs"
+      }
+      children {
+        node_id: 45
+        local_name: "variables"
+      }
+      children {
+        node_id: 46
+        local_name: "keras_api"
+      }
+      user_object {
+        identifier: "_tf_keras_metric"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+        metadata: "{\"class_name\": \"MeanMetricWrapper\", \"name\": \"mean_squared_error\", \"dtype\": \"float32\", \"config\": {\"name\": \"mean_squared_error\", \"dtype\": \"float32\", \"fn\": \"mean_squared_error\"}}"
+      }
+    }
+    nodes {
+      variable {
+        dtype: DT_FLOAT
+        shape {
+        }
+        synchronization: VARIABLE_SYNCHRONIZATION_ON_READ
+        aggregation: VARIABLE_AGGREGATION_SUM
+        name: "total"
+      }
+    }
+    nodes {
+      variable {
+        dtype: DT_FLOAT
+        shape {
+        }
+        synchronization: VARIABLE_SYNCHRONIZATION_ON_READ
+        aggregation: VARIABLE_AGGREGATION_SUM
+        name: "count"
+      }
+    }
+    nodes {
+      children {
+        node_id: 38
+        local_name: "0"
+      }
+      children {
+        node_id: 39
+        local_name: "1"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 40
+        local_name: "variables"
+      }
+      user_object {
+        identifier: "_generic_user_object"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      variable {
+        dtype: DT_FLOAT
+        shape {
+        }
+        synchronization: VARIABLE_SYNCHRONIZATION_ON_READ
+        aggregation: VARIABLE_AGGREGATION_SUM
+        name: "total"
+      }
+    }
+    nodes {
+      variable {
+        dtype: DT_FLOAT
+        shape {
+        }
+        synchronization: VARIABLE_SYNCHRONIZATION_ON_READ
+        aggregation: VARIABLE_AGGREGATION_SUM
+        name: "count"
+      }
+    }
+    nodes {
+      user_object {
+        identifier: "trackable_dict_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 42
+        local_name: "0"
+      }
+      children {
+        node_id: 43
+        local_name: "1"
+      }
+      user_object {
+        identifier: "trackable_list_wrapper"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      children {
+        node_id: 45
+        local_name: "variables"
+      }
+      user_object {
+        identifier: "_generic_user_object"
+        version {
+          producer: 1
+          min_consumer: 1
+        }
+      }
+    }
+    nodes {
+      function {
+        concrete_functions: "__inference_sequential_layer_call_fn_6629"
+        concrete_functions: "__inference_sequential_layer_call_fn_6733"
+        concrete_functions: "__inference_sequential_layer_call_fn_6720"
+        concrete_functions: "__inference_sequential_layer_call_fn_6656"
+        function_spec {
+          fullargspec {
+            named_tuple_value {
+              name: "FullArgSpec"
+              values {
+                key: "args"
+                value {
+                  list_value {
+                    values {
+                      string_value: "self"
+                    }
+                    values {
+                      string_value: "inputs"
+                    }
+                    values {
+                      string_value: "training"
+                    }
+                    values {
+                      string_value: "mask"
+                    }
+                  }
+                }
+              }
+              values {
+                key: "varargs"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "varkw"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "defaults"
+                value {
+                  list_value {
+                    values {
+                      bool_value: false
+                    }
+                    values {
+                      none_value {
+                      }
+                    }
+                  }
+                }
+              }
+              values {
+                key: "kwonlyargs"
+                value {
+                  list_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlydefaults"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+              values {
+                key: "annotations"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+            }
+          }
+          is_method: true
+          input_signature {
+            none_value {
+            }
+          }
+        }
+      }
+    }
+    nodes {
+      function {
+        concrete_functions: "__inference__wrapped_model_6528"
+        function_spec {
+          fullargspec {
+            named_tuple_value {
+              name: "FullArgSpec"
+              values {
+                key: "args"
+                value {
+                  list_value {
+                  }
+                }
+              }
+              values {
+                key: "varargs"
+                value {
+                  string_value: "args"
+                }
+              }
+              values {
+                key: "varkw"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "defaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlyargs"
+                value {
+                  list_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlydefaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "annotations"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+            }
+          }
+          input_signature {
+            tuple_value {
+              values {
+                tensor_spec_value {
+                  name: "input_1"
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 214
+                    }
+                  }
+                  dtype: DT_INT32
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    nodes {
+      function {
+        concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6689"
+        concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6587"
+        concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6707"
+        concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6601"
+        function_spec {
+          fullargspec {
+            named_tuple_value {
+              name: "FullArgSpec"
+              values {
+                key: "args"
+                value {
+                  list_value {
+                    values {
+                      string_value: "self"
+                    }
+                    values {
+                      string_value: "inputs"
+                    }
+                    values {
+                      string_value: "training"
+                    }
+                    values {
+                      string_value: "mask"
+                    }
+                  }
+                }
+              }
+              values {
+                key: "varargs"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "varkw"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "defaults"
+                value {
+                  list_value {
+                    values {
+                      bool_value: false
+                    }
+                    values {
+                      none_value {
+                      }
+                    }
+                  }
+                }
+              }
+              values {
+                key: "kwonlyargs"
+                value {
+                  list_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlydefaults"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+              values {
+                key: "annotations"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+            }
+          }
+          is_method: true
+          input_signature {
+            none_value {
+            }
+          }
+        }
+      }
+    }
+    nodes {
+      function {
+        concrete_functions: "__inference_dense_layer_call_fn_6754"
+        function_spec {
+          fullargspec {
+            named_tuple_value {
+              name: "FullArgSpec"
+              values {
+                key: "args"
+                value {
+                  list_value {
+                    values {
+                      string_value: "self"
+                    }
+                    values {
+                      string_value: "inputs"
+                    }
+                  }
+                }
+              }
+              values {
+                key: "varargs"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "varkw"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "defaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlyargs"
+                value {
+                  list_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlydefaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "annotations"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+            }
+          }
+          is_method: true
+          input_signature {
+            none_value {
+            }
+          }
+        }
+      }
+    }
+    nodes {
+      function {
+        concrete_functions: "__inference_dense_layer_call_and_return_conditional_losses_6745"
+        function_spec {
+          fullargspec {
+            named_tuple_value {
+              name: "FullArgSpec"
+              values {
+                key: "args"
+                value {
+                  list_value {
+                    values {
+                      string_value: "self"
+                    }
+                    values {
+                      string_value: "inputs"
+                    }
+                  }
+                }
+              }
+              values {
+                key: "varargs"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "varkw"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "defaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlyargs"
+                value {
+                  list_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlydefaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "annotations"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+            }
+          }
+          is_method: true
+          input_signature {
+            none_value {
+            }
+          }
+        }
+      }
+    }
+    nodes {
+      function {
+        concrete_functions: "__inference_dense_1_layer_call_fn_6773"
+        function_spec {
+          fullargspec {
+            named_tuple_value {
+              name: "FullArgSpec"
+              values {
+                key: "args"
+                value {
+                  list_value {
+                    values {
+                      string_value: "self"
+                    }
+                    values {
+                      string_value: "inputs"
+                    }
+                  }
+                }
+              }
+              values {
+                key: "varargs"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "varkw"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "defaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlyargs"
+                value {
+                  list_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlydefaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "annotations"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+            }
+          }
+          is_method: true
+          input_signature {
+            none_value {
+            }
+          }
+        }
+      }
+    }
+    nodes {
+      function {
+        concrete_functions: "__inference_dense_1_layer_call_and_return_conditional_losses_6764"
+        function_spec {
+          fullargspec {
+            named_tuple_value {
+              name: "FullArgSpec"
+              values {
+                key: "args"
+                value {
+                  list_value {
+                    values {
+                      string_value: "self"
+                    }
+                    values {
+                      string_value: "inputs"
+                    }
+                  }
+                }
+              }
+              values {
+                key: "varargs"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "varkw"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "defaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlyargs"
+                value {
+                  list_value {
+                  }
+                }
+              }
+              values {
+                key: "kwonlydefaults"
+                value {
+                  none_value {
+                  }
+                }
+              }
+              values {
+                key: "annotations"
+                value {
+                  dict_value {
+                  }
+                }
+              }
+            }
+          }
+          is_method: true
+          input_signature {
+            none_value {
+            }
+          }
+        }
+      }
+    }
+    nodes {
+      bare_concrete_function {
+        concrete_function_name: "__inference_signature_wrapper_6671"
+        argument_keywords: "input_1"
+        allowed_positional_arguments: 1
+      }
+    }
+    concrete_functions {
+      key: "__inference__wrapped_model_6528"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "input_1"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          dict_value {
+            fields {
+              key: "output_1"
+              value {
+                tensor_spec_value {
+                  name: "output_1"
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 1
+                    }
+                  }
+                  dtype: DT_FLOAT
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_dense_1_layer_call_and_return_conditional_losses_6764"
+      value {
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "inputs"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 100
+                      }
+                    }
+                    dtype: DT_FLOAT
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tuple_value {
+            values {
+              tensor_spec_value {
+                name: "0"
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+                dtype: DT_FLOAT
+              }
+            }
+            values {
+              list_value {
+              }
+            }
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_dense_1_layer_call_fn_6773"
+      value {
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "inputs"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 100
+                      }
+                    }
+                    dtype: DT_FLOAT
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tensor_spec_value {
+            shape {
+              dim {
+                size: -1
+              }
+              dim {
+                size: 1
+              }
+            }
+            dtype: DT_FLOAT
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_dense_layer_call_and_return_conditional_losses_6745"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "inputs"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tuple_value {
+            values {
+              tensor_spec_value {
+                name: "0"
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 100
+                  }
+                }
+                dtype: DT_FLOAT
+              }
+            }
+            values {
+              list_value {
+              }
+            }
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_dense_layer_call_fn_6754"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "inputs"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tensor_spec_value {
+            shape {
+              dim {
+                size: -1
+              }
+              dim {
+                size: 100
+              }
+            }
+            dtype: DT_FLOAT
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_sequential_layer_call_and_return_conditional_losses_6587"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "input_1"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+                values {
+                  bool_value: true
+                }
+                values {
+                  none_value {
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tuple_value {
+            values {
+              tensor_spec_value {
+                name: "0"
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+                dtype: DT_FLOAT
+              }
+            }
+            values {
+              list_value {
+              }
+            }
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_sequential_layer_call_and_return_conditional_losses_6601"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "input_1"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+                values {
+                  bool_value: false
+                }
+                values {
+                  none_value {
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tuple_value {
+            values {
+              tensor_spec_value {
+                name: "0"
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+                dtype: DT_FLOAT
+              }
+            }
+            values {
+              list_value {
+              }
+            }
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_sequential_layer_call_and_return_conditional_losses_6689"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "inputs"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+                values {
+                  bool_value: true
+                }
+                values {
+                  none_value {
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tuple_value {
+            values {
+              tensor_spec_value {
+                name: "0"
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+                dtype: DT_FLOAT
+              }
+            }
+            values {
+              list_value {
+              }
+            }
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_sequential_layer_call_and_return_conditional_losses_6707"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "inputs"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+                values {
+                  bool_value: false
+                }
+                values {
+                  none_value {
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tuple_value {
+            values {
+              tensor_spec_value {
+                name: "0"
+                shape {
+                  dim {
+                    size: -1
+                  }
+                  dim {
+                    size: 1
+                  }
+                }
+                dtype: DT_FLOAT
+              }
+            }
+            values {
+              list_value {
+              }
+            }
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_sequential_layer_call_fn_6629"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "input_1"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+                values {
+                  bool_value: true
+                }
+                values {
+                  none_value {
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tensor_spec_value {
+            shape {
+              dim {
+                size: -1
+              }
+              dim {
+                size: 1
+              }
+            }
+            dtype: DT_FLOAT
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_sequential_layer_call_fn_6656"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "input_1"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+                values {
+                  bool_value: false
+                }
+                values {
+                  none_value {
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tensor_spec_value {
+            shape {
+              dim {
+                size: -1
+              }
+              dim {
+                size: 1
+              }
+            }
+            dtype: DT_FLOAT
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_sequential_layer_call_fn_6720"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "inputs"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+                values {
+                  bool_value: true
+                }
+                values {
+                  none_value {
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tensor_spec_value {
+            shape {
+              dim {
+                size: -1
+              }
+              dim {
+                size: 1
+              }
+            }
+            dtype: DT_FLOAT
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_sequential_layer_call_fn_6733"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+                values {
+                  tensor_spec_value {
+                    name: "inputs"
+                    shape {
+                      dim {
+                        size: -1
+                      }
+                      dim {
+                        size: 214
+                      }
+                    }
+                    dtype: DT_INT32
+                  }
+                }
+                values {
+                  bool_value: false
+                }
+                values {
+                  none_value {
+                  }
+                }
+              }
+            }
+            values {
+              dict_value {
+              }
+            }
+          }
+        }
+        output_signature {
+          tensor_spec_value {
+            shape {
+              dim {
+                size: -1
+              }
+              dim {
+                size: 1
+              }
+            }
+            dtype: DT_FLOAT
+          }
+        }
+      }
+    }
+    concrete_functions {
+      key: "__inference_signature_wrapper_6671"
+      value {
+        bound_inputs: 9
+        bound_inputs: 10
+        bound_inputs: 15
+        bound_inputs: 16
+        canonicalized_input_signature {
+          tuple_value {
+            values {
+              tuple_value {
+              }
+            }
+            values {
+              dict_value {
+                fields {
+                  key: "input_1"
+                  value {
+                    tensor_spec_value {
+                      name: "input_1"
+                      shape {
+                        dim {
+                          size: -1
+                        }
+                        dim {
+                          size: 214
+                        }
+                      }
+                      dtype: DT_INT32
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+        output_signature {
+          dict_value {
+            fields {
+              key: "output_1"
+              value {
+                tensor_spec_value {
+                  name: "output_1"
+                  shape {
+                    dim {
+                      size: -1
+                    }
+                    dim {
+                      size: 1
+                    }
+                  }
+                  dtype: DT_FLOAT
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001 b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001
new file mode 100644
index 0000000000000000000000000000000000000000..98807d26ee9f40e99330ae6a5d2988c640a320ec
GIT binary patch
literal 88424
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

+d4W!E+~y333|Hr9)dThX)0R^VOV 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%0D8?`HBcY!+5c|#2G|*uNPG9Q@ zKZjHk9kmT*=HD{r<4#f~MLjetTU7hEdofH92AD-K~!*X z?ZbEv-e8?Jd~Xw?_V*CY5{KdGE)K=*DYL?A56*Yc!CjjE=$1MIO=mgb>hX_hOw?nT zwnK#0Z8-_8U3KX9oFO~gu8|+T9E787sI}A2DO}YX~$k=SyQ`k$@A1tE@FP_kbN2XN3 z&Y&C04M?cjKAJP-3z0fMg%)foC2B)1^l9@*Y^k z=jlg0XU)ZL;)>94-G?rA4j>*+dPw(6Z=(3Yn3a3B0{)6mhGE``#)L&N3vUOb*^h1X zPK_5GJI$XfP~OhIcuW`{`!@3Mhz;#*)1~jHkFPuT$A_NYRzrGOd3xJ_8Eu}Mc=bt& z7Aj;UQ{`K>I61?SuHP5ScwbB5^-b=Aajsfj_lN?2elfw+=`M7~$4TtA`zMIlJ8{

3r8j?9kuMIsQx|%S`f^jW-*}C7X3% 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 !xswBeIdG!<4 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

9}7NmN#I%0%U{fvRdqTtD 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 z z*kF-h)?;lft3GKd`>kynS)V_j*rh!O-{m74V$HnS__|?YNKN=-20DCGh8&w^hmf)< zm-uJ0%*t*vGVsudulweT`TL`|y)Sggy@wK{v~2=i*gOd~opyn+bJJn&?nlI`PoBQF z`NsF2nPaW-REmG*xftX}`9V@zDlO}=gWI};%mknF{3FRXbjH)~$ z3(Kp>?&dW6zA}#uR74G+_6|Lo!$_l5l*C*R*|OWv2=(&B#mCanBH)N$~@al z=4ED5`$ePj}C~QfQNB4FuWw+YWV0x zP&S%Cr2N0~vJQfS?zaqHl2U=o@4hmkPY==OmLJH>2{VbIUkCA6k+52kzj1>pKURxUGS2r`+m8+;)m!dF-b)Yj33w3kII0%1n zi7GjTL376eIAhvG&DWXG#_g^ocfK*6ltKQIT|PC|b|>rB)G^aF2WTyGmT@*`VA+&3 z^6}n1;x}?O{HWAtFV5M8PQuf3v%zid$)X*sw!#QJG5;0nOTVXy2b>!urhlTzAMTS$ zhod0ncmgi>T!j9wTIsqwq7Ct3&D8En67Cf8_rtA@_%+L%1-}%``D2dLH4kI3+ER3{ z&%uK`g6LHDDEfB90h;k8iC0oyh@bB-hB=~uH}}XBw}}Vg?YmW2Ri}-nPTTQ)&nLQ8 z-$!65w^I z4V&fQjJg#|;n1TTbclR}fs>ZuFAYll`ke68t=W8EYAt=zaFKjhlg8#x_XQ_Y9q6xf z!k15VaB09&lsjETRf^mM7Md2^DLlsqIwnxlr`H93%pCk?=R(}&ucPOgNNz#u7wleX z59hrl_~PObyxq5P?8rYJQ1fXMvdPDA)}sW}@fDcbTn&Z|D+n`yskmwGU8*5Jg<9GE zp~stdBfJVlmwk_DmUaaW-C4j_-g5)(;XYV1Z2|7@k7WB>)|1hy$DqUiFKtlG#pgZ` zIOQ3c_`M>Ve=hjA_pR{5^-8YTq|gcM^Obapt^~#>E8vEDZTxN8gVIYfaQc@*yjh-y z@&W_xP1p$R@J?cW$4^C3@pPKx&BEmKQYgFR8I3dvM%nryZ0>7^$mp9i_~LP_J=jgn zlHSn1D@SSR>t&d=ND3u?`r))c)6l*7Fh;FS!vC(>!t?$1)PB7Io{)FKvBR=xZAmHI z>%uwPHWSNrVt8v>o8SPo!Cmcsth9B7A5c^A#Tn~vEPQ`lV*7Wh_A znpOQ8#aL^+K-Y=C@!{sHvvK#nk z_y7)?p2WQg&HU!2*{I(XhIZlh>{*9n{1~S?Ot;X*QB$sgqkI-A$vcAXGf&~*>nZ43 zlZwf|&hwKUEs6HV5vZL10p{L!Mv=|u;MFI@4M(!@$UH6lceIHAH)awhdp{);BV+N* zfqIlle*;rnQn0XK4_=y6fDyr~Fg9NsCw1zwS|1Xqk?&Dh_3jz?EG@_WNy<>Y=Lskz zdO<~jkhK^RVZ-aR8hrl<9CiCDen#hKNa&2kIpb=O-JFP>&R_Y^XR=m$v2^5>PfW2mW z2?O_g(z~B~nO5Hnd^()TwnW>5RU!itmYQJsqY1>sRbZ#HHP~FaLgM4||L;d-n1zKz z)JGY{Z+7Q8r53|FYY|9Xx|0s%tHF%m2TV<@6YTW2B+FYOSOw{F;XEA%pOu^OZKy8k z9K#Xm%$e{p&lxt;{cv~6L!#TBPVSYNG`MNBQL}4X;LedLkhy3-z4YJ*>3-@Af95X- zw}?TZFDV8SFYTvs%WWDQZZ8q`sMau-eHVjeiae}c=?_&qZj=6d6NOo24oT(P--VyKJA1Jk|u9Pu7=dBli=8@X^_DE5b~jusJ)sx$jp3> zM-!BIQ|mVJ?UW1~I<|_2ZEAq%*ZP4p`C7=8@};HQ|B{b4wW0d`XRt0fL_Opb!Kc6mZrv^tW&%7ZZ`Q{b{IBIoP;NWUehi8C+PR5_Ne(qhx6Pw8kH2sQ)!EN z7`|){nJeszyjV60Gydx1pD$1A50tOKPxnRHgBB6==_5xb==TNQ+S>!?e|N#PT5q^N z{;%1`J}1FfV;a4mq--_e$0E8^7MWkcMX>mZGA902V%BJHBpMHsQGVfZ#?B=Q!_F@w zmuh?|*vz0w+GdJGba2@g2PgZpqw!i(j4ZXO@lb} z7@j4!Xcm!aJOXvU{5jQ~esH<<47vZUft=|rhIbG2KyriNM}3$9_d`WN%TF3#mBhnK zivXhk`y^}<2by>EFZb)gTQajZ7F;5Vpj2S&#APM`7j>K@%(8&uyEb5}eGpVvS-{Tu zC7`qE19cSkwM!pPg~;v6kiA<3_G~RD6F#NDQ+qkMzWx)DmR*5qH=|)ZnBdHEJ8&9& zO+Iw2hs2wM#PZl$2;JC4KeWX|V`C9asB_@YOxJ?CYhOwC<5<|NCD$hDByBWgTW&6R+7l|0UqydWMc$Y*nCO2+QLDvdN}Mm?hU_teRy$Ma~54k zv+iZ#Fe^R{M#fy?V-~nl^9SeA@$yNsTS=MMj*^2&r(#G+T*=5^vS8K^&wz`m6Y1M* zJ@#=|7G2z1PP*1zp?0_Q=mWUKasK7pWA}A*!saZxw&xmUE);XwQr!@iS4(etnJ_Vy z;>Q^Y~ zKPh;d+)mPE|BjKiL&u5R)(moPrxO`3F%r6mw79No84NY~Ogn|XTIJb;wBolOsXV%c zj%qf5M1N5*Kbis8ylNqAzX3e|lt4P3TVmU{6sj6{i99KIL3iwVODsQo;^h)acGXN> zy!IxWUf9o)m(c~ZVvz)+xFi~re`L^(v+|&rs|u6eXu+ZW82Y=YkVt=GaQuea`o*yl zkh`doR#%9j@x&#>B;Ydtesu$NT(ccLjP4WPeVsV6>;YYHbS)%JzfDI?siwA()wIEX zH4|JynW@iSlPmG(;Z4^#;A-{Y?AjO*`4IyJX(72%IEOD0y-lL~1Q)oF56E>dBZYrgk;L?u)VS@p z#nF~p^7W4vK2O{M!~XqbMCMoGIBy{Y-S=gl?9laxl@RjeJfq zgsY|lCJh6`Zn_B66}FqV9; zB_JVWpm#3mVkT*Cf|b&Vbl(Y2P<=jvBnf=^uk(W-RsAm3C+60dHHM;*D5klgV1Ycr0)Ik4W0>gTmX+jNiG%Fj=_!epJwfo;xC>bNnL6b6Ew8OIE<#j(TRx z*XN+QcLZ2(hyhHsrY^yD=&fgtqw~XY;sFP^qw|~V`C3Ype9YlcnIC*z+5?y3dTF(1 zDZ;0ORWM5T7N~=o-SzU0eds-;0El8cF`;@D<{5ARfk_Rsi##oBf%86){$n9zTDU*mUsGM*(&PlYUwkDdVlp76{+|3B z>w-HDO0l~xS^?wW2rBy@k%JAIxG(hwGclovq`JgHfp`Wc-0vY%9~>s3H!6sKpa}H) z$fK6OGMsO)0@XNY`1V#Dv_JKd!;WsWLde+U?h)mM?Pc;+QusW0<&g$>C}fb!LBhR; z&bcB3*wI1McdM}lQ>GF%xeJ`Z%@U^S&PwLYTpMzzYzo@`UIybe=fQ}KL=w1Il?;qI zN0OG#h5HkJkez9&;BxQ*`KXx1$18u~wpR4O^r~Xy(uPQSOekwNW(#*N+>1w#t*~cp z1C`m}L)R}!V!|K)M0R%~OniERgf9<_z(gu!#O z8zk?P3k3e>0aMpW5jn5#a6T~-M%XTZ>f7Gz5&bM8l55Gou8x7}(|7X&&6nZSY(uzI z8v$)=juRc@A<}o#gWp(~Nh*H!lllLBhoSZonDr@ud~lgTBulF;qaw;Ex8XCH|2PM{ zZQn7mL+S9Zct88EB?qe)nL^T=gI0I^Qoy9)FS9Z}5zBmeCGM?`CK2N5H9)jSYH{^)@6SBQf8|K;O5=m(pepibQdu)op%jmX+I~7j2 zcU3I6@|pu$9?!4;xqUNU5c>5_1u76?HHoZ$^PR3<=>lW+j3s~HJ|~xT-O;orkv-LY zl^n7>3_)|U;hm2TIao6XygM`D{@zIN{1pvb+*%-f*qZe_Da#nT+i*8CjfH-VIXh{@ zWv*XKsi9tbFQk1>1p5?eaGrkvevEPC# zBiWd_{*1m|n80NJ4lB(}*y2cYHmpa7ow+=P4{^|EccJw9<&3s3*%- zh5g22Gg-V9HlD!kptW?pjZG}h+8S+sv_!S=44j!p@(tmAnz zHc`iv9lK;KH0p}5*7wv&`9v$W&&QJWe$c~vOgCl+X3k;9y&l0H26J}m*3a-E>ojWY zm222NXD*v}?J3^9YR*Pqac3Q#%QhG{edI&O&Y?#W22o=BRrdYOGthdem0xHgaLv>v zvLDCIVO{P`VwDFE@Kg7SuxriL*-r8n^arP~wHi9?)p~ih?e9H^{O==#{in@}=5ONn zxT#q`UcQ*u$~Z}*{Uq3}&+kyr`6Ix8Fb9KEXR%c_{R%uZ2pk<16wKCWe&H+^KsGkjr3#I9U?R91kv!c;z}ZZ6N#^Xa0jOd zBzOZkW|F|h_H1V+lYi7~(;!*&q?G@w{RH;}Mw6m9Gs%PECnV?JQL99;PZ(hQlZ?C? zPfYYIP?Ar?)CrwLQxEKsQ6o>b+sW7al$#;G{!A)Af zisaR?V4TSE(HU~IH&B}i7&VGfRExqx5ytSmF_WZjW{6nBGp;1*GxD1jz>ybE$ghPj z>+GV{VA`B6;+huBZS(zyTkBTv0Xsi)C+Si+J>nYEIa`u{{!bR=%=+N;f6DaRju0%^ zT8n`;sgTy)W;tshnN%!oBpVAN$lk&C^$qXpAbnUKJXYC5>uLv>5g15}#t3)CEFL;q zMnSHDI&tz6u#Lf^`R>(IS?>kjv}f%~V&459s?{zOG6^3p1_!vnY zEzC&a9}lua*AcJxZo~%;bD_JXMCh$K(M3~d8`_rEe94^U6wrevQaO z|B68n)l@?x4>K5&bjF)PHX&!-82qnM0*!s<MILg z6-A(!ID$Vvw2jM5xzGHqm<4S9lcyZg|T?P6x#TLlWXH|PqT$^4{dG3L~jF(@$R@!{HA z7|ajQyoaM`(5=O^;K(F2-cv&7j8Mf3LXBS+dcex5Xg&_g*D=Y4-pJV7f?>xA+C89- zqpbi>G>*m-qyNw`>Ej`-I)hG9GZehG8R(MS#Fcm_*1ClClhN^E zgZ4gbiQgSMWl0{C^Ol%&MIG*I9jCWDTw#IL2=tYd$A>zLF+2Pl`1=&0xZ75mlI)4j zj3f6a>^8IA^CunR&moR3rMd3!=$4`$@@#e=RtvqIuNIToG_h8?$uJ2PwA?0Q@E4zC zzNHJkw!(UTJ+VG84R43F!mh7bAeq?+4f*M?*fb7e_vgUme^qd(@*YgAu7Z;~i+Iz5 z&EVW{6HLe5gf{jcdH=!$Oizki8*SbKUSd7acT|$x7=8`gKpzyY)I-d@Ag<9dlYMnB z0zL>F)^`TFa9Z^wT-+>-@_G}YU0c{ex1PwJ-7|uhK2rv&-FHCD<^ry_Z6>3OuEG|V zad1Oh70%9`2clI!_-^$b{KLa%KzXeku1QY^-Sgcr{q6zyx8f1_M@)ekvWcwG*H@r3 zB2(bW6~ml&O%UFbhNt5zh1Wgl;8xei}QF)DI_0m3d6C122uW zY|L?YJZ2;f*PiOaJ_kT5d&Hm3*qx%A*73{fT2t{zwT8$zft!DDl|S`}}{@ z-NwU{t^_t_S36-*5k{@HMF8%mUby9W4G=>y8rzep$DGJ z1dA9_@nAhX)iMr~`a`Lr;(dDL$4zeYm)X#ImSB>s3_fk~U9>e34(0lkF;ilJfp^uet^#lo_Eo%W!bqIKITc+R9Sq2a#{@r<2tN;frMvUAIFWOS@VayWro% z;Q2UA>FcK+&V7^)+@M9-9he;;$4#4I%sE9*#G+6K`h0%`B?J4pgWAdX{KEryoEHbz zH?HBj>IiS}W(t=7R%e5)xW3yS*CyEEy&Dto(ilk~ zk+;F+zs;yVeJ8DW@QhwOsE<+`X3?IJm*MrH0E7u&xtf@uQ5&SbA$cL4pt$WQuNHtv8?#U7j(#AHXU*j&hfe-5=lZ&Wl+iG4{uiv@1?lKnXFc><1n&iB6z5Uvb7!td6YfR~+j z@CRada1)ILMxNO;$dA`T-9@YM8ai@4%xl`JbB2z&$D)GCTFlGK#}yUcywYtooRa2_ zGMV~d5B~Jj1#{HS3C8U%x2g0YWo+{h?iUljFzM=xvH1D~ViA`{|C~PpSAk!aD&$&2qS&RvK6XgpN6chJSnui{%;8O7Qch|-CgHNOpXd;320mhWW{C&QNLax~ zK7Rcm*>&(VR~B^FYFk_!cVHP04^`s`sdR)zBlp3b`gM@`JJ0I05bU~eRv8W#)RC-A zb>8$+7a6)B!yZW44CX`US(P6pFbCH`Ok*~2?U+IA6>UL0r4LqTI1p{c`CONaGiWTb zr((}7n327+;IHRY*jv4v>ZEp);x+GlEhhJ05;vL=gIkN;`H4R&n1(K6&TijWrrv*cedz0SlJ;>j{JH8V@NQCwvL~_3 zT(Y`;Q&0y@yQG2>)|6w3oj0_oDZ-7ZJ_Ia2!n8Z}@cz~*l6bHXF8bEc-~AE|?|hPI z-Doj*;h+JB2IYih#dBoeniOyzJqm^;CxK1!FbQH6$-qlv=u~|vxSZOE&R7>F_LC#Y z417SBm}wL3{P7_5Splw(K1Qr}9%HZV67sVDdP&NXOw#dTKXm^!A!qz6$)4@feB!AN z;(OSGv=lw3XMzRC=#0lC|Lk`%KC+0S^F?~0RFr+c@lE~H$6fTOxgyy$+mf9B9!ng> zF4DF`soZQ?72;+Sz>e%tC;3zQs8OyqCt51QUVY($GfW%E+511~+=z18CHaVqtD`ti z;S|9}b$Xw*$1{=p$TZ1E%+iV+k`WmS<_f*slHa??mVG%^0r|G{LP;WhuXmP@^wEay z${S=`%QCpy_k$KG+QX05cVw~uMBmL&gf(P6oIP`r zY_PN>)ulpSS-zKierQZ?%ol;Y?49^LE`?;qj)p6Q(u4p>JTFoNyB_)y-^u^cuX?he zGx;EY#g};~(16ls--@{g&Q`&L8lOj;<(PZ01J20@L+C zlq_6+oH+K%LdS|6UR*?m7M6?z`FrPh<;^;?k^-AG%-q>)i54RXY1h7y zn;TYIz1P3SuAd}n?Rr-N`lBcEPRoag$CUdJyrhnZr*)I<+Ir;TiHWFGZb*;++fUht z<}m8d7vdi-+VJL388wDtI`yhDD6K0YH;y+D3CX``FR&tJcPEiuWy^5&qG@pKT{32V zp2ja-Uwdp3I_62YkqUrFKY4F1;4_4NE7FhIbL+DN|Y}}bfMrJFpJ8!4b z(Mu)K+-)*cJ!?lPRs_XOHQ>{&Cb-$Y2@lOs!VbCvTeh9!-5&2mnX&6=&e9mHt_a5* zmlq@{dNfKb_ra*u+1M`@L#5_h(Z13Vc=X$Qx^d4iEeU;v2BBlH;+-S^Hgb~Sra8yD zxDLTWR+?_i1j;suV@;tV-pCeu=jOF^mEsHfxNAKuZh1vyO~ugGwuat(dj$6Dnp!=) zt3+>}TaA@Y()8Pp1pI9?gm2cFvO~vK;RX3xkTVdY2B9_lZ_{Xe@^L1PJ)=q&ru={b zBNf`Bx|1GamvS{rd$>1sZmj&H7~JY`ol30@!<+->sL_)Z_$6qNCa65Yc|osXjMWKn z?oz~%yeqsEE7LHs_ZE!nKg#!x;^EF6J=lIc3;r!rz{aR_D36?vF7g}Dp!EyYwhZ6{ z#;dZ|R?kJ%*%3Ia#gWc8+JOP87TEo!0}}3fpx&iSj9Gb)3mN$nB!0%S;RmjxwBnU_ea`rWi_+ZLmJ;*G_mwc@28USUg)NMfGEG%$Ctb<5|tiDA^!bvHd{#b|^>LiiGCmFQXY7*Md9u^!N22>~S7q$8)(Xe^EBE4vl z41zZTbxxSD9yX$^_usMT8aRox55A&Y%4TN$+XnLD&n|kl;~+WJRf$DC%h|XZ1611B z##G2$1`olD!6K4@3+;68JY!sY@Ev{Z=h#p&bthjbTS-5Bok)HbZK8W@&r<&@-b8Hi z1rj97(VLgQGm0W*<=IgX-7~|_X0XFQG;Fc*ATyp zpJpvO`q|dSoAK*830ROjK%4yB1+G&U)BQ}?0fG{eH|G>}ws&aAR?i{}+VyDgcTKM3 zb1EEDDyIr_$8+~r?5Cr%3{ix2AQx)3~y+A`MB-JlW;iW#z3Y z#ea!*MJwSB^>XYO+!DSH3Pz@LJ?f$Kp4v>bldh!27OJ@G)+IhmPn6BMD6m@>tf0AR zY4rLY5%$N<6Wlhx5!C3h6nPg=!EXuwObgt*X=wT>X5IR4^xTF)dVBwFDkJU1%dkhd$P+M)5z$S>*RjMCN{p~JFVQ?zz2Sw!=AE=q9HNU_|3C5 zXz!s)-YNS%UGhMO(w4JiPjMY74lv*FLLWvA%;HCfQY74D0R9`E_=3-lzv@kt6fZVN2ox8u_tsZ*uW@( zSNP_Zkf{%gg(r$f;r<#+xO^}NCgm*S{YM!>RkI*lv;^O?y9dmCxfM3& zL_vB)lshl4on+#nb<2(jG}@(%k?S54_-p(KLA8Bg(J! z6=&x!vxVw|GqBt&861)n@zOCpP&dzlg??+Hv*Z_y-A}+;#-0f_j{s?B4d97AA1&<9 z@2Z;!hks2V>tq;c3r&OBmeuugg$%oQvkJ_O8Rpu`VseS=$!`#U`9q4y*ghD2To=~%SQ%hs9E9J{X*8dIu3Fog&N2~12uOV5NQbp!}sLW zSJTOKL4`Wqo8Zlq$LQhxkoQdfTqFEgGZRGx|H<>&52-=UC(gLfg1W~Gv!#c&)Oe9K zoNV!e)jRYUE#nwSexZqDUYsP$8-j?k=zRPl^i5s|ti%g}%kbFGcjO9xt3GS~Gfrmt zS}gM^rmIhWXVe#&5*=NFITMXh;YmkFC{UkB zo*sYJ3F|&hfZ)zd;`m)0bc7xFg#v@p>Dx&3vf991Z5CzP=LBP_%wMa(;Zrm^R|5A1 zxT3VvuKG8U2T;m!nbpt53i!LHoD7|apczezsjOEG`P^JXpUtqs&*!hwS-+FuVo^I4 zFAm_+Ci;;BU)<{>zQ2c=;T@djn9=ZhogAI_C=ouqldv-P(14VzY|ebcOj718gU9OC zVQgGZKtA0_4p4YX3Hv2jU7!IUrzyWl;J9b`7tv_nF|RMgE2vFuuaYx zN}UI-w&a?@3Y%gs>xu2Co<30?kBCjVsIk9iG*8^ zfUL=*!AJi$$#7E!zc7wDBlCxN+&E1BT0bQxXO9APn+}*|k5sp)68yBI!Trf;a&glO za$HV?y;yP>8lS#`JmGVhuha_JD~j;(;8S#o41s?o@yub#t<2vae@U08GSu#_z^7xg z$(FW_q-=?Oy?_67nCg*Fj>ew@!v;IB>K+9N@uKX5H?lBuS0?@OQUvGj_5{0U(V*e< zjZuvI4JjAx>ekr`z6hl(QoFUB`#UX+gbZ{OUtyp8&@?rg9hHuEx^!XogEgdN<1V`3 zzW`#^{Q|~$j|Rj0?c~GF*F-%+hfG{-M#>J*(F!sBMLL*U8`Fq=Ld z7G`9{MD?RQ{azJ9UP2@Z(GDei+7w*7cr$PG>oD1pyMS}C4yRXtG*H(bAcbqz(0fNs zVK`KTA6Xy^Ww%aod!}g6qaTpm(%%P1{PIz@0Y9M<<&UqF;ZH zhTRCGe)~d58sAT5TT8I&1J+>IJOf8v(8|tBg)@ z@GuOk zCR&C#^Q925WatZ8_2F_zp>6@2CWQ}B^#TL;L6bJAOsfUoQjKwl`MdXD7kEv1N4DDp%54?f|QfMDYqI zSCcj2Dwr_p0eRToCpd-_p!}OCi3`{Y+0L%ee?=b}i>qi!mn*nSvrP4sV7xtN4}`s( z3K8krAXU7EYdaFnwdRe2H@`Hkj#XbIXD*x}^c})iYX`nvArO}B(1snKBZ;$H8tt{P zff^eFh)FdE@x!{bAVwK1MHHyNQUj;Ad<_w^n24Zpo4IIYMU4F?3+!JHm^XbL$VVLm zm-EXoIo6%pCCvh-^BN$3!Vlkny@Hor3}L~?VziZ$0Zo5l?sU)t7}?$Q*u!*UvdtJg z!%x;v5>+I>hc>`&=RAyj$S`xPqe(^JCoXrv2FCGd4rA{hg_(N-!0zZ9@*tAJ&hPOs z`|3BK=lWZtxZwm7BuwFX*?3q|eE@C*1%v*m?=eT@ zqYX`{aY2%=DT{%~sX_*FVK($DoAS9G`E1qNO#a-0F;p_sl{PBK817f-~0OrM0V}ZlRntwg!OrIRcE}n@LE^7I;vO@T4z|*IyG2QMTsb%qv5O zO(q_<+KY2u>;~_`A(F9an1r3HwURvM$=+RD0F44uCw*BSIj=DlrffE3@4B9_I(1pd z|6Dhtu5%mfBO`MeF{4&e;@{6CzPm~s0`1YPb`r$SumZ^t6|%jNS-bu~#!J`WyoJTIf8L&`0W z5Q)ICP-7QkIk;C1uF9s9jTMQU&(~&%$=4(z+Pk{=O1wQpBLDTB;eEw)aORVyJlK9ICXr82Jylc7~64Pt0Nzfs8T$0&cXlG&)k z7pk>Ee&f&jM{Oz)ZXiXjhE|c({ljp;HVZATU*fLC#WDtWYU*=NjACZW-C|bIUQ+Dq z4OjjUt6jvMnNu?!tgGgtvL*+LlbxXbc3JZcCZPvCsZ*C6IPLf9xa6H5g}0n(O}nLLdzexg2gXd{S2D>R%X(g4F#xhcxAB1^^hgvfZSfO8`=~#6r_~mI zDLB)b#K#s{?z#MV-UZ~+z3Q&rGzAl zdF+aI^0Vq38MqS3NuF-yCW|P-)?^#Jswxk5QN2vT#ZgeXpny&IP>t!{xkyxyjG3T7 zR7`fWhKhGc+Dm!X{eV1vU$c+4a>)Y2%|z%c9A!ht9mHQMrNpvp4x_x}CUe47$Y#$^ zBMH_xBosFmA5+b$Y6$SF3c2aJIFr3vg$Z#(*8t(Z(b(JQ@=pCsE({% zS4!xvU&P|`Lt=HLpJ-h>LXt~Uh|zU7BDQ~!@D+xTAT4S7Cg-`C5C|nBmL}}%ecfc5 zR2C@>=_GeY1IW9J93NJ^f<*V7Cxt)mlH!HY#Bs}ddheAslBilij6+SK&F>IX^S*;5 z933H(tupkh@dbG2WD@zZ`~xvr#FD(+B2wok2E7Yf*}GpKl8HhYn*ZYnc{vyi?{!K@ zNLn)yb((aL2I2=D2{7Kev9sVL0Mf%&_LQ=5r1@U{v5LJ;nBJ?hjcnWCJ z6COtpUABiB|MMC)ZNEVhYBQm8-e1u4j3VXgnJBWP5{4%`$eqR;c(?ug+S;&c*Ia5=eIOd=OfW!0Odw^rrP7 z=gr& z*=={0WeeX^Q>UAW(;gK#*L5MyHU`VJ z8-vwsUz&e2AN+o421^6pp(kd|#Na=EnDJi`$Ao=cfZh)j4)ZY(hbm9}F$5BIe?PikK&N8mimyu4D zG)OAY<|76bl;)dl#98zvWW+2q?^HHoJ_NTQlaLGO@~9jW`jE?a|LaEILQSyKL@}^J zJL$Tev(e^ESMcdwz;)K=)3=8PsrOC4DVb+uOof;u`Q&g6ou2&>J>1Hm_X5{YwImO0 zMmZOy0oOAhx{8#4i6FJ<`IKGT98wQ+=(xLIaFVDFjBWO%v^myEf%O8G%?shJlp>~LcTnPwPIBmH7uo8hi3P3j-X$Qo>2))RzP}hA1(Io7A3ltdu}+NfaFUD(c}?5`gB%4vbOdD z-a8dAcoG3=zx_c|sgO+DGmfMWxq+LT3%R#01onxYVfO|cMVF=A*fNd0$@ysGvI$#1X2OhE?<~|@@6^mh>VLO>{-v=S>S7Y$mhcbs>EUtsTqTTnKWFnaKEFZwJ0GIj z4RetEzhT7pSA^E_*N1s_XCc1ZmYZWEknxd$@W!>odR_>tx_m$FY7bc5(Fy|A9pfE6 zF3YouTTSG?J)%Xu+)(3;TeNtKl?7X$MhA}?61R}~C`M5e=5#uOVW9+l^-(&!YK#Dv z2xT~n_Z~H%? zPux4!yq(o}N-dnRi7_WFA?NUM<|-7*t{^LRE+S`qrI;plPa=?i1$!^ zXnk7%S*PDr8~$ZG(J5O;23+gdz#mmS5Bu%JNbe{(uCBu0Cbp96;j2i=v4L8p!6nSx zCK_ihQ9^Srx8W!IbjZo2AMmgFN+eBMjzs%!Ahm~^nK=Cg$8^# z`WE861>4yjf|0~uPlA{>@@-a+A1d}Ea&oak^Qb5!?W z*@tPw;GG*Dl)j3m*2jZx%r&h2EdvcJzhz#YB z<}KgQWg9y@u)GjX1=zraw;^POnLg+RY#|e&No>)9I9BUe88kPzk~LMWNIKe<9Dm1o z304=9$hZ5*d1@vR;Y}w?K$0F>RX}3BB}iDnC~h)v!eW8K+_k93-i)%xTlhoB!>@+y z=<-%FZfyiz){|7=6JxS6@gkczB0~LGR!VC23z5?42brMYM|k-CMzT8X4cV7>7fm)R zkiZSkaE-Sz?@4A5T9{mh=BP#D&>aLV&6PkKIX}h$M**z!;WJ{mj)3*D8N@cklFrM_ zL+&I4yQ#m2?_sStyW=}`{#FMiYkk2yNSA@iOIOg}yKrKkv%g6$U|cXR=UEGRD0cG)S{}GZ1r!r?TJRbG7$Qy0VFbp*uc!2tcQyi@)>W$ijNfVJFU~^2V`pLt`lczvFvkr zlgJa4@@pIS9bQ3Sj8CGO^B-TiV8-heWlnv!b6)Vt?Iks{4KkjOrCb>3tjE_3j1(?VIf5y#esa>m0aO%>=(O zMd;sGNsc@`h}Qf{h0N1hoKsc_Odq+xvGcZ&^K>3OjmUJlO61Pl zAILZAB`R8Qk@Ks|!^=5Y;Gp9OX>Yhq+Oa4~8qBpgju{NZONP7?A#ncwgnGa+czN92m4JKC>z>Kw~FlyP2Ru|>L_K%)KMx`H3#%e&>YcD7(G^GU_#=x)q0r~l| z65`rK*f#F{PhrMlHZCk2b_ z0a7}n(6a3p$H4;jPC3UjvdjUgzO#@JS`B+j2f*N-HOsqt0>&NtK*-OXEPmGs4cLJ` z+It5~Tr9|^mIGv+gA;^Fd4tsMA^5et3Px6B(Pv*2!1BUAfWI2d_m9zFMQ4C@&MD9` zO((YxXQR6|-7rJC2fl552z}3nz&ouMQ0E)+!l?qplvGGlz!Ok3yH6b67r{yKrt7L4kM%+F4W&_U6xFyKfO0o@jx?UpZHNdpKN*_yiTpf5LFB9$xujKYcFv zK8p=&h=dmlvRgChMJ@+u^&jV0)wub*c{_HJ^>{V$pLd?U7%)ihEX*Rabp7CGR|>2P zdJJ1d{;~@;NwbI7zW}uC7;HVC2zj$Tq4@Y6ko5Gm=y%9~|AK?yL-lmtLX#>ot5J#9 zGt@$4T0g_X@?28F_@LVQac)oN9UM+oCfe6}7=@=bu&K2NP1Ih&88@bpjec9O1k&ct z?2Ad=b}*u$aF6@jvc}&GgR1Z z!ke&Kg&QbtNoM#I?y|}~Vi2-jfG8`h#od7$QG-PT_VEvblTW9i$Sn&|+gJs@Uity8 za=V2G^!o8BOHoFn?UlL3`A6vI7BwQ$?|~i-Hsj~kK+-F&GW%ro@U%k_$WT3++B#~0 z4)fNOFh?TbiYr%i8DuXgMy^*>0`XgX^;8Haa}rVMi-NE#2??hFG8&Nzv0V$ za>P1D4ZPL+ag?VIY;6_-SCd{`KySc7b}`Vb?7@8TbfPvpWmEW^1S=Hq5;@-;fIl2Z z?D4EZB&1M_H@rTJZS5|RYmHanX61Z5Z@m^t)zKyWheU{ z&l-H!gYC>Hnd1f!OQP_jt8Yn!Enzxk__6SeFZkr&Ur1tq5UTlFQf(<*#*$VisQzLM zFWgN)mfP=h%Qbqdoyt z;%s2q+)9>C@;BQuG6ZujF9Ao@GWyDu>qLFG4~)B6!_br&yw7xpr542~F2V|C2W!C> z&fTHfo=3ixJwkgf`Xa0R3+PV8GiH;mChWK@fNbTtzSLh2^m>y3jc2bw?v^TWVdWf{ z(RCi_+)@P33>9Sd$qgw-wNS-JW$>PqU1*VDG>$-r;PS{e_{nfQls_?W^i(9;l-PiF zr>ufq-!C9LtuOdyq6i$C^@`Lt_<@htG?;F1lyt>b(}#*T)2|FGz@3lt^JxD@W@nw) zIWc`O79~z1VzWhVaSmIp$;v0zh?wVKa>H#3%j5r@G!pjZ#mE^X~>exu%o{RB4sBb zxL8>Nl081)WYuooTpCVWCMBcQhDXS&;bt_;xQi_m-UrPKnotmJkBk%cQw3b!PECZt zrtEXnI74gZa zSx5t3UE*d#ZT#%vm<~qMWI3}PS-@54#o%{bmDXJ8zuP(8D0 zQX!1B&;X$x&!Zc6=#uTpk`Uw+fknINL$7M*cRjFO+JAtcz7GSkS3S7S0$*5#*hsY@nUi=L^D2uiR^@uA>NJ1(|ss19z zn(rXbA_;cW=b4}z{DajA<tN^gx%r;km%#y*o5 z@r89+_*vUp;#wDo8YCa@TF2qY^PbQ$d03bpNfH*PLhm<&TcxmxgAMP zRS@RhZ(N}mM+enf;HcU_>^ED69Q1TTo=BNeNQlP2mShtgzZ@sN{fBct7UQ2v_GqT) z1}u8>7xw-fhMWB@QObIGh~hX$m5Vf(7Dst_alMDR^}d`QZ@G;0>QAtGW)4X2!W@fP zruT?T=scVw(Tez;bMYryAAd>skIhcO*neRqS~as6iyzIvdVijwV>aS2w&ny%sjbDw z%39DH=WJv>@)gh6+lR&-+PV8VmeoGzfcl9(BsJYdp$(77-+mY5SapXgl)HlR(v^u& ztxrwRhfL;JoD|GEavg09Nnw3Ce)wk2Nz|`g!}QVbsqj0E=zPH(h|u{91p>h&WWpQX zW!0j093$OOQ;U`Pe3>LU@X=P&ZX)N%5o}epiiwDo*3VA*9VG0p}#Cy0vB@rjaI)J=RHnQJZYHn4m#NOk2n8BMwc03f&u>b?C;)G} zBu!#tuENyrFIf409!?nwK|-x2M6tY+V>{~6xr)bOp~WopMbjFD=Vs!PrgbQPOp-K9 zyrTA4?WWq#=HT(4^N7ZV8ob_c2B8KMDd#uN>{eEToR+jB_f_T-9qrY%pF72o`SV(E z7M#GzEj?II>^0Je48vcKV_2>e%JM1kk=tt5AxJ#~whl#+u-B!mX+tShI`RSBb)Vv= zQp?Dmm?4}xM~0T%b(gqJPei75f!OJy6S~^&PiemrCOyI{NPmhV*|o%x@Fir^uC}gZ zThwW^@xW?0X{1hS8>B!YYYe|h3&+WdL-^dlTH<1ANZAnWwY(X$uIPXsB0$Cwg0w|_?9x}z5GGktGM zGhh!dk%o)=L&?T6~_>9y2Vy{ z>yUlMLhJthb5A>GCPN# zlP?ncKvjG%RW_mzG5lQZ{^J!!Z*vGTvG;=GInS9LJU-mBY%$*Z@)H`{MnjU47+m-| z58}7ns#V+&$XqVl3AbXzkfFUk@O{1x%O9&?Y3YsZyRZM@y3_nHbS)owD&I6;9oK*s zWvP=*Oa>Lm$7NB|f1@$(9^2ilhT=mK(Q_v!+!qvW-fjFHskppF`&ODj>`EVWygnPO zr@upMf^V4VD=op>#zs-cEETf8>NzFS^QHFpwYfMv!UJ#HK9h03B!iL;i$LJ7&49Lb zFmoK2gT_!P^|WmP9HCMuZ`u+8^ zi~}O9L0eab7I)c>w(W_5EUr`1V(Jg-tr2LW3XQIE^IM40gu-*Spu&HnW|DKfi{%fa zR!WTX*Cdmseipf?hNFyiUPL)43VL1cV(}C9B=`3tG*?7}5a)D!=Uga}=)8>XP(PUg zmn!rt+=V$@ZNfGLkXibr19{c4L-(?K0bFX+m4LbB@bS zc{HkehVq-$jWhU;6YT?;=%o+G#n2XFYgbd3PN%jkyK2&i*BsdT7mD ztB9V_=;6Xdv2cb9GQwAWAN+8h0I8?I6(>bk^B8dq4L9OOxrw_8H56cqaOlt)&;VtsgSr+_ab0Kk279bZ|59+r`>#xpv^?tb z6(ReVn38enIAr}P1^4wIL-&qfM3+Y1BXNz(Fvq8uIyhd0KJaU>KRG{L%!$oBmy}k_ za^2##eJ{YzfV*Pa-SCAg?zlN>1KMxy3et~WGE%G_u~9fjUT^z`HXOf%x`h`L+vKC5 z?`(nOyCsQar6Zaw(k4;+#F;do8|2=+I5x5B2cDZ31)GKo%>^DOvkiSxBzt)Y6=Pq? z@JpAmOE_2J2TvC7j^BdABaJC_o*pdul!VXqm7;*jF07CxP0n=QL6?1-(TAlbilSDbIJKuY_(;T`5|{@I&bd%+R@Y;;A6N^Z;TtB@%9nY{>v31j%hOD8f_>b zz7G!l7Y3qfg79Wy2TUkLf#n@9_OM$Q+Q1%x8He~$KezwXWE2dR*2743)lBsLh#Kcl zEn#<@UIx~u(&>tW(NJHo7t4mPqyE~QL@B*nD4SFFDUZ0-u&gGZ?Wl@|j~vr6>SQ^& zGP8)=sW=WNbWg(eee03b%2H(h?;)DW8$rRZEn$DsK_pwN$DZp6C13S4;ecy0RtR{A z-ag49FH4s|(Vblozh*52h6}Q4UACZ~u>zlM)Q5wA&!d0EPl?V*D5xxmhBaD7u=eI6 zwC>MJuv&48_#15F_WEDJupH;j)jJ4~q{WVjN+X5CL#;9p#3^3x=M0MB( zNz6S*jR-s9+*N(#R%tAjdiIQ|D-(gNJ#96E(luo1!#&6}`U+b5M*?8yW$N$fCd?<; zPFhQkq2%06@S9`BD!w?1HjOE9^ZAb`!v8KEP~(cSqtlS2R=@eza7`|wziXCT2CU-o z&3IXG0tyK~12w73>GRSV=(eT;tZSD=8mgCS?b797-{W&g*Y6g7Rlfu+T@b}isqwQv zVk0pQ9Y#yNC|LOBAGjK*quN`am_)$|^a(A3w(E;A4|1tP%csNP?baaAb0zBjYf;tE zM%3RiV1904GUc#Yzq-d}JNG=~+|xhi(lxdO<*f>5W@8VM?zG)HtPK%Fz-tvli zkhGgVGqWDg8sPTT{~bb$NIU#J=?J2MsSqr3p5F6^2X>m3a7DWS0w1|TO?p0U@!1<>2bnfNEY(Z@0#sET27S=7RmGUEnmaiu9uK;dn+`n zKLRV@7<21bh*9G_hCXsU^ZX8&6R;HAd7AM4r3G=h#^RXdXzq-A6nd)cxt!;2M#evA{t%S=P=d(3;R-$E`2R`nH9PJw11SDb?tD$m~ zE$=u+{Z=xi&wMN-!^4SCy!9p1#(9)SWWvFy@fJLt8;R{7@X^Z#+~L!|VDRRpg2DAy zuom5b&)P>xiBuizm5Kn7*#$&eb_xvMhtNw44?uBEIqbc1k2R5xN9w-uaAkG}JWD=8 zKR|nN(fS%N$x1cP@A*unTBt$C%T4IKz$G@Ypn%bmdy4+dS7b~c)iIU_e}W$#Mv1|~ z5K(={{8#@>oX|#Nx1+Hj_9Gn)Yn|cdPan8Fp;F{77|X{0RDsvBdr?097fnz~=wpf; zxU0?P9CiDt8(bD@_;3ilA2dM?Y6r=kM}DBHVFjt@pCbj44>)t%V=6aS3?8KO!Fc34 zXpOXmEky?@J*&V%Wv1!=K{D&nno6*L8BvE7w(nXTa&tdv+iX1-2< z)HY|>{*wi{lgcc_0A@-RcYxJy*oA(*B&S4lP zX90}I4p3K4>2i!*8mjkg25XU3a6Ho+F2yL3sVE=zhHofp`lAD9792oCwF{{li6L5y zg844{;M4CGYQvo)^r;nU>`aX_@Wf9Xg_R1y>nq}9NxB~#5BZ3Kmqx&*Q#nL?(jR2b zX5)2ct{`zclw&eJM;Ql}gUqlyH2&9uW_s(w^Y@G4N^B2WAWpMsGh(?+q7IKca@|2F;14mULV|Os@0-6 zj}Gmxr|5Z3Fy5dBRsYgp-Q!{OshG>!W1pe?A$u?uN<;BIA8`B25YW8l4RUT<3Dvs? zZ{&7%)=a2!{0CJym}&?Ywo8EFPbE59d?q6Px+G-#40zFB2Iey}(Apg?aK<7NW%otl zkNeuthmF4}S!M>*ACH3m+tI{rb|DN$uHp6uQX$oOKcL^8$hS)z-btmiZ)eGqht)^O zuYoW)e0?u;Hu|txqc6!tT}L`4IG9vy7GynTZ^A-jj>AVq;%PFq=v7e+_>PMMofUyU ztr#IZj;$oYF~vUguL7n1WN0uv0>ba#01;RXP1BuW^;A50#51Cavl~kJX+sV)r@+eZ zL!fS-io#at((?CB;L=hp+HL_tZx87~+|fm}_vkM8{%-}hcl#MFQ&WvstxyvA8&Vn_Y1K$%@LhSSy z@YIVTR24=8yTg%h&^46pybzRMufvGT%LH|L(SWWi7)m`t-Oe%a^kD&G`CuVQHw%R@ z$C>7NR|Mc96G>vUj*!vS{B-YIB`l;Xgqoh;AUXeZiQJ_O;_Kke#3jT+jc^{UKOzfB z@js9z_ggJn&*i9Qr(slz`wS+z@KJ6(q}X=BzX?0o`*AVwrPD;PDFBjrCg5LW4bIMa zFhfF{gzsyp?GrwPW54}F|1+@ z;nms#l)rokuAQAkM#uV@eP2$JXqRPVp;sW0RC|gS78IcY!QHr_Lz;+rPrx$u=XgTB z6QldaWQogGwm@z=?Rl~uUyIQt4K_pgvsn;9Sc2_)znsWRFCkTivT(cT57{Jfig+q< zojc(z%)2#1%#8i}Z~@hV|K{>)5AGGk^M0LR(_crzt*iw6b=MNq+9*l7b5&XUb)h(5 z6+byT7*4hoegucP3HU;(6SICzBTn$8uys!c?D%C@Yjkiqx$NGBrBlOP}8D=QpuqJaf_Lq~+ryB5IYx~JGXzLFg^;o+l7KKRf1F7^R01`?NPz>ClZ zII}jCHkM6>{V%UTSVunC;%ks{TNUWt6@Wj~g55C(=-9jn)Wx2`_cPx?@z{A-+CK+G zx);#lZ82O<>IrVAd9Z#gk-kC&Gd+i&L6FG>XcblgW$7@W>nFkf=Q+^x;IcLAncS2i zljL&ur%><;2>%xf-}lJil#W{=IKP*18D3z7Qd0HjhDg@HY5}CDPYNEMc*^2att15RvB(+>Q{m zO_aik@OWx_OA?6{l%_S7T7$;KT_)7Zf7RRXgMu; z&6suEa0n8rwQ1hsdidCsMbzXOG-B!v*%sH}bmS(M@0woqS(8m57o0;3UvM43fM2yw z8ZFVHT4VZ7YBX{>c?x$4{y>I)3vturUg92}g(A{EQ5Req@d5w0sC0t~s83&tpDepa zLB)Giwpg9E7t6%<2cCiF>}habc#5npoMQBxa~X$Mf{^)25Hb2!DHDq)B-MfQm-0v9 zI^#2Bljt+ZJ+Fb*TWX=d*8(VAjf2?edJ|4fqt|;8 z-G38L8ThoBpPR}@;#Xzh&6og$ehI^KCl909($|sXz6v~S?TIHGuaXL%672eFHCiGz zigjYI)SjETit}cM!=v^VMD5wb{nvX!RB#M))u@Ox_Rqp1bPw~2>mIb`gu>}r7Qojc z4PKn{)yG~Q*?R@n*tI1vlBOj%bJaL((GN%2MzXN}+I4()$9(4bD43`7JEGUNKiNxX zhp8m%Pnavc(oMRy{3oIU0+psrWRyDl@udt3;*^pNVHFH@aRAnYwo$9oi}9{T zWm1TG31#66uJhr31Qz2x@(IDcn;wU6@T-NOu<`b&lgoqYT;a`pvQO(z;tHxfT zncR+;TF7itvtcdKpC(Lq`@g{^rWDz4e4OO#htjDt>ahE89mh}1!`m#oapIcUyk2u3 zqJPVfWa`F{(vH2P?b=R~CmjS2*JqQ32j0QdGD$RQhDgrVOxBJPfrA6WJllI+gwL}Z zJS_KN+vF&iAK*xCbo~W~KLhxiV;He5Od+cZzrkgV4dm|rG=l8X$hD~u;!kN1)5FoE zQn?(867+R$iU?mm!)J_vD@1h81 zJNgisE{hA^XA!xDVT?z>U-V)nAI)D@h=X$y>3_ZZu=<;s$b2D<#(h#zy%FbBYq&sN z*kM4i55rh#trJK*vIWo5=_27alPIBUDOy@1Yvw)1%?VasN4Mu+Ks~4LV~t)O`k~xS zeJ;v@M;n*&l+N78YSjbSZ01(v;WtVyfFK+%RD_@DznN2ss;p_M1Z;cyiV?0h#XPeZ zWIt5Ns=Qr>1PxA7GA&-zH?3T1k$Nc;K<^^6x0$kb(sryazddtQC>%L$FrlLtNI`>- z1);r^sKCF%SnNzHD?ZN=ok5SlVZIjO8&QDfRW2yVM+r(>&Jn+hQY@d08c1(?ghR%R zu%gnH+RrJw(NiyT;-s(=A?HM7e4n7K096)F=hF)kIgi_f5`59_WgocP;hep}JZ15x zSoNg>@QryusD1VJ7xa{?R*u1bN5L>{<$;kf8IPs zeuEocuze$n%Kb#y;>Y;yqIPtkaue>#5`*H1G6|#{ahZe`}Gj_Ye_(&qd5N7Cql+Qj*}CYJV8J4J~q$_ zM%ERJiJ6cw@4f#zy1XfZ_F(eK-Bk-wi9E7S*AI>u#vsKi~XJog|ca&qk(C z<>*D7HK@|HA33$n2kXRxsLtX#CyiP}S9?d83k+4@y3h8=+4wo^T=R#$JkN^#5~qq@ zUdmv1Ik%vQ+m7t>ydu0jdMl~*io}Db60o{_36a(iB@>qO$#yR*^1!N|ZMAYBj@_0_ zzw0hMw|oH!+;)*3ealB44mRS7VhU$$S0Eb42F;_qqz!f-mv2>hR53E^Tus(B6|+CKv=b-aRixBx7fWSdfJ&)7JcE$$Nc!bmj`y+y1O|b8 zD|m|q<}V-@od1&K-i`Fidk!RUbC8*CWi%yfB2H9#w5cyC@1XI86gju+7$dsefE8-G zghmeQ(y5N8NLG#~i6X1%mTgxl6feo<^(vAJ@4Z>&>N~^SklxKPT|~*2ARd`)yRD zHw!8C&?w!v40$bFM-(jOV1fNF5aTnZH60J(3ySx!!}HZh<(LV!@{pl;=0(hxioIN3 zAj9rj6$+gprtm;E5!EjqMxDYj)YKITMkU)AE&Dc#)$g_ARKG0p$n_v7TBl$MFFUeW ziaW}GGDNmTUtc%J9=25`b=EB@NK(16pnpI!50D{ z!8H^7HP=I+)*WP~GM(#{a6XCAZ~`9F0KO-)TNSo|`L0iBFe(r(&+-NRJ`ae!Do&fI zOCqOWUuah@MIY}^BaPdSLz8kSs1D~a2Znm_n@8p7PCzhvED;Eov{S%#PBf~hpH3&q zd_lH*B4F-F1gw>qM)KPmP{kC3mb@|qGq))4X!YXw(|ggzItuL9ow4kA+bZ_I+x?_dVlNu~DMm+}m_`n+GG&JplR#E23StWzQFmGv z$0*-T*Rk@<;>>xqRfFz~>(48!w!S4v1zi-O$IT%0+8CE4U=O~X!l(CDG1f-Y$@OLf zGWREUO)y0)t0q7c<$Lfe*Q3O=@YHA-`(E9d1v zidY0oyr+;#(z)86*;821Opuj#<@Sgdc4Cp~W4Pq;2tK*il>J_vO~w!DlY`w4u;v>9 zQhz~@gs3*-KPmG&$@s?y3$ml> z0UG2FMs*&dVDv%`{oYlHiVU2Xj>nlO|CK4;;Fm)Be_lh>zaYjpyA(}pHniA%UJHSO z5Av*9jTO9NnA^2~DSLtSSYs#%506+^izLh>$=ifUS!X4hx+DZT^XI|N^P!jyv4(q5 zADJD~k0M7wZJ03XVUv!E@B~+tQ1A9z!Q$@}?*DrUg+=G08|CwGudp?oUtq&hXJx?V z$s}47pTIDDi{aje+pLY(J_vi$i54_uBdyGL=1k#yylvJeD$w;LX?k%9zMq^zJ*`)% zdWj3w@0IcMIVr*?IG&ooy&-$?=q=6pQzts&Cr=qgfDK5VtdXz^TJjFJejS8 zeQlhv{#_$_L~#wMJl|N`VJv~OE=Djed5Y-NiL1Ey{xcN(NS#O~oMwHsT=B$GO|oms z8m&5>&SkIu^?04buIahUnY;^_7iE)_|qPx`}L#3OO;gHxE}K@?+-b_ zpNJlmar@pPSunyA!oNP2Vx`AhYGYU2LS}DhviVdG?o0ZN#kr^CjRP`p%IXaYm6=Vw zkK6-yVw&;gg^g&Rq#q!Wghz!v(d`? z$-cwYghO;&FK>Kc)xmtM6mme)mA; z_fB%THXjBaWa7rRwd`;J$FeEZp`|qxQQQFh_JI=lzTV(d}F>|GFIQlN%1J^4GxDpPZvN z_XX6p-UYjCu7BQ7KL z!*vR$q5Ve$bY2XEfJ6OfbW*JuPAJvD zDeb$=r6GS>pPT*sRJ9QQgzr}p$&a2%BJ;kJ{O8|F&-t7Ow_0k*q46^$sXd8=-SHzihfdJbIxdir zM-Pa`+Gs|9^f82pJ>d4iLdo0OW03x<49z>8NKRk#<92XX6O*oIWQR>JVG6Fp3XOZD zO2P(oWXp+n!)-{MSxLGjHj|R`7s=Tv6;`rs8p%D6a5xzVze4h&%V9wq%PyM$!-~^Gm0v zPuwJHxkuPv%PzP~tFp7?2FQbAD_&{qN%B$ZIBV!LguGHT={pO(Ny-g1R=YU?LFz6- zk8VKSDn{5w)s(F5osBntS;7{qxrycWI@RVx{KTbOQn9p94VnB;jhs+>g~jySD5Vd2 zr1YTynciPTpXjK=JOTDGT*eLeSvdGp95o;yp9c+Bu* zCT-)W^lh#9ow6i3`GKF$9<=b}Bd?QD@_AwP4?cOc;C|iyiOHL4%hiiBww_ z9T6SGPTWcYn@efn6`v0LFSJR+@jdY5!Fk+SA4t4LIEIQxA#2|72~F(UNen(u;4(u| z(!AS|yw$KGKHqk+#SPPNvxy;-rE!Gq^`B&6dMh3)KTqB*e#zX`4`yHN5+!=xoTtj@ z7WG-|0+C6H#HSKh;`@9qsL62-sSPa0=Vjw?--=LFk`scv&L$J>uv(nk@&VWUu7kwa zVWi@A4vCj7AU+%us(NuMd9T1?*sw%I5D-lx*svF{fr#AhJFK7rMvdL5p#CH=Vl1GN zU-&&BCKv(p$M2tew{K==cILY~pI3I~#c0yIN%>^u@t;Uo(M59Oxfk6yH=2svZj+I* zOXznm#5AGi1O$bAPla`TX^hu0S}-q(f7hf<-y|8)kcV6N+!O)z5zVHyO9H9)=|b|P zmjz!RygZfO6g@_h0*2Ay)lKMexG&9b z^rXeVI?@H&Db&CJM&f@UgQ}-{Qqibf8uCsBPx>kcp8m0xMwG3G>AknpT%$vLO@F?S zg7;XsIZcI|Tt6Hf_`Hur%_~u8Rv|>V4+A)nL#s{=r1k?m>HbwZU@L4wSykVY1Fz4K zoPIV`5&4V^OK_v=YbFD7GN&^qvecf>nNa>*OYheng>))|ZZ2gcp+1t1uT_Or->Tv- zssicTeU9V+pNwr$B&T_MD(G#K0bEV5WGT7A5)A9x7G5lvA#(hJ(EhK;;h? zsK&b*^h)jmCdWgePn0M z$xxm>2`Vp4gM>JDv`wAg)Az$vV)GP(tjv-#*}WMtYR&MZN)PN^|DXbh+7S-F$Qfk4yb?Leb>ZImP?(XjnR_POk0$O>rCH71bZPu0 z6wol1)12oIp85L9RJBo9t)!ZiP4woroEV7BJdC&}&-srR@cUr)I!uKzkqk;sGs78w z*un+*A}Btv3~Vlqg~#8dit9(|DpID}qcszPK$MzPs=VZlc9Ts9uw z=v2{HX#q%M$3l)N&K9q){fe6=)TVl)zZ|U8Dx`i@s`Sf2c_=zGi}YO>LcY$ZP&gQ@ zM&@N>kXq{Y(ntOITpY`-sD6PNowzg;>7=u?*j|U0N|Rx?p*nqO@Emok)9ywf&UUB=$*!pA$Qw<=q_FO@SfAJz}&wGj8mPC@7 zH}}z}mVvOrYAu@HGn{6*EJUO48F6WIOrfv*3aOlX8?>xf5;buH(e{`}@4;M{Gk_8M z7uA#dI*I7g$xOv4elJ^8<~)cFa~EIRTSuDa`;+Encf<|dYtZ6k7Wcdpsqmh8mpD0P z^0_)1oIs?@EgOAZ@nSvy48n2(=hXW#8vUvt9o(=R^|<*tm-R3fp-YaW+s_Zl@~zjz z4?SihmklgfG})3O{+lCfH}G<7`1(qA2y(Z3(+%P*Gqsze)eHZ-3Gy+Pn}>L5|g zI8B{r96^(vzJq-^KcK!#|y?zPxrdma6pn`X?{Mp1-$6y*PnALTo2CgoEgNNoI~&M@1y3<=uUe__>-QmW4M}e zqey;k5ejn1Ahz9DOoLe*G1L-gx+B`N(g3?I6XN+L##qh>@w!Z7Sdwjz1-A@w+I@3e zu}g?6hFIe5=IPYxyb1Q3Xn{r1hTQsXrdar@iBvbT_)f!GJZ4rJXL;8cTL&57b$O=v z;uK@NXU2DQ+f*U$f6x@;7nz8sKA!*DYUD`f!B_zUq9Eoc1xp2SUxU+6)tXX0|I8-Lk-59=eK~)qGu_ zTr<3?cL;gqV2yt|WQfIfhB#<}HP$_9jw`P;kwN3ssonX-)Nr;I#lB|P*l#mkU9c5y zo#+qDNg=Gfv6E(n9TA_Ywd6kkK8I``mr9orYaDo&#VdXj;>$~lQQeMQ`i{@0(#NJ$A&%c6a12;j|vMNX&vRdijdlicRn+ywSIP9Fj*ZSL? zz!^U%2BRChz}>zaB7%#+_|`#?=AGm&85F@Gqi}E?8ldDK`NQ@I6QwR6|F14lEh~6C zf=h@hfee#9ppe9G^yHzmcq733w-_g<^H6eB1 zJ$NL|gt2i4pE-UmzQx%wpV2)oE#m7Irrm5*R&TriMcI?5FO zyIeWm$4iUzr-9zlXt3NIsI+yILdm>T5UK*5=W~N*|z)cAfBV}%uI#=_%lhQ(4U72_HIcK}6nQp263Vf0a!H+zE89r{x z$SQT^Ykprb^EGRmDkjB-a1qMY@SoFz?^$igMFV;Eh5fMsMcQSlP_+(f=#G{Xoq+3q|;yfl^( z2pCo)B1R(PHEVUQS^GoHI-P0OZLhgSlU_Sb`hRIM=v))~p(ex5G#Rzmq{65$mP|L^ zE>$=Fz_6a&K81m0R~T4*j6tXKTT5Ww9)o{3*~8e0ANfhQ)lcE>U19K^*p;_J z*^rN9x1r0+?i7VKQde@@P~g`^%PQg5g?lS1?c1#=*tA2z_ERX>b%jFDk5TA!?Q03_ z+oSOB0zu0xQf;$Gt;L>}NYG}bL)+QU{yy7Ad;janXbO6<-Q)>!Ni6@@k?j_lFgIS# zhgqlgAxKBy+&%Y@H}51%z(k{Hzztowc_#kIYZAa>M8__mG2 z-1D!AzMzn|Jf3W)|^Z)<= literal 0 HcmV?d00001 diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..c20d8afabf383430e807fde58270f4ff7c92fdc5 GIT binary patch literal 398 zcmbQn@*$OhfsKPviiv}fK}I0n*~8V@JHX%5FT~Nw$2H#H$;;I_B;Gy9F~Ea^U5G(p z%3@ZHEBvOMEJwl_O!%`?ixP|D6ALo+b5l!-GLwt-4fK=qOY=(f^&CS&f;^oGtXXkj%{$(r+6K}d<; zP(QgZje%hTs|n91pMdA{fb1StqZ*47qNWTcA~}hbsYUVSnI#$V<*AwJ870NK2Kq^v ziN$4W7!p{7m^e}t9?W6Yn80lMt3U99sG=CqrFp4UPZ%ONg_t?6F@jWR09BZFzuEp# zSW(z;RuKaSqe27g9*HtPHz83)iM~Pxph%7cP$i?nhxx2)b@qRrx`qJ=7(uw8ao InputsDir = unittest::getInputFileDirectory(TestMainArgv0); + llvm::sys::path::append(InputsDir, "ir2native_x86_64_model"); + return std::string(InputsDir); +} + +// Test observable behavior when no model is provided. +TEST(TFUtilsTest, NoModel) { + TFModelEvaluator Evaluator("", {}, {}); + EXPECT_FALSE(Evaluator.isValid()); +} + +// Test we can correctly load a savedmodel and evaluate it. +TEST(TFUtilsTest, LoadAndExecuteTest) { + // We use the ir2native model for test. We know it has one feature of + // dimension (1, 214) + std::vector InputNames{"serving_default_input_1"}; + std::vector OutputName{"StatefulPartitionedCall"}; + const static int64_t KnownSize = 214; + + TFModelEvaluator Evaluator(getModelPath(), InputNames, OutputName); + static const std::vector Dim{1, KnownSize}; + + EXPECT_TRUE(Evaluator.isValid()); + Evaluator.initInput(0, TF_INT32, Dim); + + int32_t *V = static_cast(TF_TensorData(Evaluator.getInput()[0])); + // Fill it up with 1's, we know the output. + for (auto I = 0; I < KnownSize; ++I) { + V[I] = 1; + } + { + auto ER = Evaluator.evaluate(); + EXPECT_TRUE(ER.hasValue()); + float Ret = *ER->getTensorValue(0); + EXPECT_EQ(static_cast(Ret), 80); + } + // The input vector should be unchanged + for (auto I = 0; I < KnownSize; ++I) { + EXPECT_EQ(V[I], 1); + } + // Zero-out the unused position '0' of the instruction histogram, which is + // after the first 9 calculated values. Should the the same result. + V[9] = 0; + { + auto ER = Evaluator.evaluate(); + EXPECT_TRUE(ER.hasValue()); + float Ret = *ER->getTensorValue(0); + EXPECT_EQ(static_cast(Ret), 80); + } +} + +// Test incorrect input setup +TEST(TFUtilsTest, EvalError) { + // We use the ir2native model for test. We know it has one feature of + // dimension (1, 214) + std::vector InputNames{"serving_default_input_1"}; + std::vector OutputName{"StatefulPartitionedCall"}; + const static int64_t KnownSize = 213; + + TFModelEvaluator Evaluator(getModelPath(), InputNames, OutputName); + static const std::vector Dim{1, KnownSize}; + + EXPECT_TRUE(Evaluator.isValid()); + Evaluator.initInput(0, TF_INT32, Dim); + + int32_t *V = static_cast(TF_TensorData(Evaluator.getInput()[0])); + // Fill it up with 1's, we know the output. + for (auto I = 0; I < KnownSize; ++I) { + V[I] = 1; + } + auto ER = Evaluator.evaluate(); + EXPECT_FALSE(ER.hasValue()); + EXPECT_FALSE(Evaluator.isValid()); +} From a1fc26030a42e9639e678344a4c08014a8cbba3d Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sun, 12 Jul 2020 21:49:17 -0700 Subject: [PATCH 119/771] [JITLink] Add a synchronous version of finalize for convenience. This will be used by upcoming patches that implement indirection utils (reentry, reentry trampolines, and stubs) on top of JITLinkMemoryManager to unify in-process and cross-process lazy compilation support. --- .../ExecutionEngine/JITLink/JITLinkMemoryManager.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h index ac5a593bb77ba..3bb56f4d96158 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h @@ -17,7 +17,9 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/Support/Error.h" #include "llvm/Support/Memory.h" + #include +#include namespace llvm { namespace jitlink { @@ -74,6 +76,15 @@ class JITLinkMemoryManager { /// working memory. virtual void finalizeAsync(FinalizeContinuation OnFinalize) = 0; + /// Calls finalizeAsync and waits for completion. + Error finalize() { + std::promise FinalizeResultP; + auto FinalizeResultF = FinalizeResultP.get_future(); + finalizeAsync( + [&](Error Err) { FinalizeResultP.set_value(std::move(Err)); }); + return FinalizeResultF.get(); + } + /// Should deallocate target memory. virtual Error deallocate() = 0; }; From fb7ef0bb0b9c6964387391a3e1759c0a3320df87 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sun, 12 Jul 2020 21:56:45 -0700 Subject: [PATCH 120/771] [ORC] Generalize emit re-entry, stub, etc. APIs for working addr != link addr. This patch generalizes the APIs for writing re-entry blocks, trampolines and stubs to allow their final linked address to differ from the address of their initial working memory. This will allow these routines to be used with JITLinkMemoryManagers, which will in turn allow for unification of code paths for in-process and cross-process lazy JITing. --- .../ExecutionEngine/Orc/IndirectionUtils.h | 91 ++- .../llvm/ExecutionEngine/Orc/LazyReexports.h | 8 +- .../llvm/ExecutionEngine/Orc/OrcABISupport.h | 356 +++++----- .../Orc/OrcRemoteTargetServer.h | 42 +- .../lib/ExecutionEngine/Orc/OrcABISupport.cpp | 641 ++++++++---------- 5 files changed, 575 insertions(+), 563 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index b3e2bddd716bb..e0cfd8bf24099 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/Core.h" +#include "llvm/ExecutionEngine/Orc/OrcABISupport.h" #include "llvm/Support/Error.h" #include "llvm/Support/Memory.h" #include "llvm/Support/Process.h" @@ -139,8 +140,10 @@ template class LocalTrampolinePool : public TrampolinePool { return; } - ORCABI::writeResolverCode(static_cast(ResolverBlock.base()), - &reenter, this); + ORCABI::writeResolverCode(static_cast(ResolverBlock.base()), + pointerToJITTargetAddress(ResolverBlock.base()), + pointerToJITTargetAddress(&reenter), + pointerToJITTargetAddress(this)); EC = sys::Memory::protectMappedMemory(ResolverBlock.getMemoryBlock(), sys::Memory::MF_READ | @@ -166,14 +169,14 @@ template class LocalTrampolinePool : public TrampolinePool { (sys::Process::getPageSizeEstimate() - ORCABI::PointerSize) / ORCABI::TrampolineSize; - uint8_t *TrampolineMem = static_cast(TrampolineBlock.base()); - ORCABI::writeTrampolines(TrampolineMem, ResolverBlock.base(), - NumTrampolines); + char *TrampolineMem = static_cast(TrampolineBlock.base()); + ORCABI::writeTrampolines( + TrampolineMem, pointerToJITTargetAddress(TrampolineMem), + pointerToJITTargetAddress(ResolverBlock.base()), NumTrampolines); for (unsigned I = 0; I < NumTrampolines; ++I) - this->AvailableTrampolines.push_back( - static_cast(reinterpret_cast( - TrampolineMem + (I * ORCABI::TrampolineSize)))); + this->AvailableTrampolines.push_back(pointerToJITTargetAddress( + TrampolineMem + (I * ORCABI::TrampolineSize))); if (auto EC = sys::Memory::protectMappedMemory( TrampolineBlock.getMemoryBlock(), @@ -302,6 +305,61 @@ class IndirectStubsManager { virtual void anchor(); }; +template class LocalIndirectStubsInfo { +public: + LocalIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem) + : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {} + + static Expected create(unsigned MinStubs, + unsigned PageSize) { + auto ISAS = getIndirectStubsBlockSizes(MinStubs, PageSize); + + assert((ISAS.StubBytes % PageSize == 0) && + "StubBytes is not a page size multiple"); + uint64_t PointerAlloc = alignTo(ISAS.PointerBytes, PageSize); + + // Allocate memory for stubs and pointers in one call. + std::error_code EC; + auto StubsAndPtrsMem = + sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( + ISAS.StubBytes + PointerAlloc, nullptr, + sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); + if (EC) + return errorCodeToError(EC); + + sys::MemoryBlock StubsBlock(StubsAndPtrsMem.base(), ISAS.StubBytes); + auto StubsBlockMem = static_cast(StubsAndPtrsMem.base()); + auto PtrBlockAddress = + pointerToJITTargetAddress(StubsBlockMem) + ISAS.StubBytes; + + ORCABI::writeIndirectStubsBlock(StubsBlockMem, + pointerToJITTargetAddress(StubsBlockMem), + PtrBlockAddress, ISAS.NumStubs); + + if (auto EC = sys::Memory::protectMappedMemory( + StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) + return errorCodeToError(EC); + + return LocalIndirectStubsInfo(ISAS.NumStubs, std::move(StubsAndPtrsMem)); + } + + unsigned getNumStubs() const { return NumStubs; } + + void *getStub(unsigned Idx) const { + return static_cast(StubsMem.base()) + Idx * ORCABI::StubSize; + } + + void **getPtr(unsigned Idx) const { + char *PtrsBase = + static_cast(StubsMem.base()) + NumStubs * ORCABI::StubSize; + return reinterpret_cast(PtrsBase) + Idx; + } + +private: + unsigned NumStubs = 0; + sys::OwningMemoryBlock StubsMem; +}; + /// IndirectStubsManager implementation for the host architecture, e.g. /// OrcX86_64. (See OrcArchitectureSupport.h). template @@ -379,13 +437,13 @@ class LocalIndirectStubsManager : public IndirectStubsManager { unsigned NewStubsRequired = NumStubs - FreeStubs.size(); unsigned NewBlockId = IndirectStubsInfos.size(); - typename TargetT::IndirectStubsInfo ISI; - if (auto Err = - TargetT::emitIndirectStubsBlock(ISI, NewStubsRequired, nullptr)) - return Err; - for (unsigned I = 0; I < ISI.getNumStubs(); ++I) + auto ISI = + LocalIndirectStubsInfo::create(NewStubsRequired, PageSize); + if (!ISI) + return ISI.takeError(); + for (unsigned I = 0; I < ISI->getNumStubs(); ++I) FreeStubs.push_back(std::make_pair(NewBlockId, I)); - IndirectStubsInfos.push_back(std::move(ISI)); + IndirectStubsInfos.push_back(std::move(*ISI)); return Error::success(); } @@ -394,12 +452,13 @@ class LocalIndirectStubsManager : public IndirectStubsManager { auto Key = FreeStubs.back(); FreeStubs.pop_back(); *IndirectStubsInfos[Key.first].getPtr(Key.second) = - reinterpret_cast(static_cast(InitAddr)); + jitTargetAddressToPointer(InitAddr); StubIndexes[StubName] = std::make_pair(Key, StubFlags); } + unsigned PageSize = sys::Process::getPageSizeEstimate(); std::mutex StubsMutex; - std::vector IndirectStubsInfos; + std::vector> IndirectStubsInfos; using StubKey = std::pair; std::vector FreeStubs; StringMap> StubIndexes; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h b/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h index 01a2b9712e9a4..7972ed4300487 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h @@ -46,6 +46,10 @@ class LazyCallThroughManager { getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName, NotifyResolvedFunction NotifyResolved); + void resolveTrampolineLandingAddress( + JITTargetAddress TrampolineAddr, + TrampolinePool::NotifyLandingResolvedFunction NotifyLandingResolved); + protected: using NotifyLandingResolvedFunction = TrampolinePool::NotifyLandingResolvedFunction; @@ -63,10 +67,6 @@ class LazyCallThroughManager { Expected findReexport(JITTargetAddress TrampolineAddr); Error notifyResolved(JITTargetAddress TrampolineAddr, JITTargetAddress ResolvedAddr); - void resolveTrampolineLandingAddress( - JITTargetAddress TrampolineAddr, - NotifyLandingResolvedFunction NotifyLandingResolved); - void setTrampolinePool(std::unique_ptr TP) { this->TP = std::move(TP); } diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h index 2e58ddd75d318..a41d4b0777f82 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h @@ -20,13 +20,34 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Memory.h" +#include "llvm/Support/MathExtras.h" #include #include +#include namespace llvm { namespace orc { +struct IndirectStubsAllocationSizes { + uint64_t StubBytes = 0; + uint64_t PointerBytes = 0; + unsigned NumStubs = 0; +}; + +template +IndirectStubsAllocationSizes +getIndirectStubsBlockSizes(unsigned MinStubs, unsigned RoundToMultipleOf = 0) { + assert( + (RoundToMultipleOf == 0 || (RoundToMultipleOf % ORCABI::StubSize == 0)) && + "RoundToMultipleOf is not a multiple of stub size"); + uint64_t StubBytes = MinStubs * ORCABI::StubSize; + if (RoundToMultipleOf) + StubBytes = alignTo(StubBytes, RoundToMultipleOf); + unsigned NumStubs = StubBytes / ORCABI::StubSize; + uint64_t PointerBytes = NumStubs * ORCABI::PointerSize; + return {StubBytes, PointerBytes, NumStubs}; +} + /// Generic ORC ABI support. /// /// This class can be substituted as the target architecture support class for @@ -35,113 +56,72 @@ namespace orc { /// will result in execution of an llvm_unreachable. class OrcGenericABI { public: - static const unsigned PointerSize = sizeof(uintptr_t); - static const unsigned TrampolineSize = 1; - static const unsigned ResolverCodeSize = 1; - - using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, - void *TrampolineId); - - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, - void *CallbackMgr) { + static constexpr unsigned PointerSize = sizeof(uintptr_t); + static constexpr unsigned TrampolineSize = 1; + static constexpr unsigned StubSize = 1; + static constexpr unsigned StubToPointerMaxDisplacement = 1; + static constexpr unsigned ResolverCodeSize = 1; + + static void writeResolverCode(char *ResolveWorkingMem, + JITTargetAddress ResolverTargetAddr, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) { llvm_unreachable("writeResolverCode is not supported by the generic host " "support class"); } - static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, + static void writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTragetAddr, + JITTargetAddress ResolverAddr, unsigned NumTrampolines) { llvm_unreachable("writeTrampolines is not supported by the generic host " "support class"); } - class IndirectStubsInfo { - public: - const static unsigned StubSize = 1; - - unsigned getNumStubs() const { llvm_unreachable("Not supported"); } - void *getStub(unsigned Idx) const { llvm_unreachable("Not supported"); } - void **getPtr(unsigned Idx) const { llvm_unreachable("Not supported"); } - }; - - static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, void *InitialPtrVal) { - llvm_unreachable("emitIndirectStubsBlock is not supported by the generic " - "host support class"); - } -}; - -/// Provide information about stub blocks generated by the -/// makeIndirectStubsBlock function. -template class GenericIndirectStubsInfo { -public: - const static unsigned StubSize = StubSizeVal; - - GenericIndirectStubsInfo() = default; - GenericIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem) - : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {} - GenericIndirectStubsInfo(GenericIndirectStubsInfo &&Other) - : NumStubs(Other.NumStubs), StubsMem(std::move(Other.StubsMem)) { - Other.NumStubs = 0; - } - - GenericIndirectStubsInfo &operator=(GenericIndirectStubsInfo &&Other) { - NumStubs = Other.NumStubs; - Other.NumStubs = 0; - StubsMem = std::move(Other.StubsMem); - return *this; - } - - /// Number of stubs in this block. - unsigned getNumStubs() const { return NumStubs; } - - /// Get a pointer to the stub at the given index, which must be in - /// the range 0 .. getNumStubs() - 1. - void *getStub(unsigned Idx) const { - return static_cast(StubsMem.base()) + Idx * StubSize; + static void writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) { + llvm_unreachable( + "writeIndirectStubsBlock is not supported by the generic host " + "support class"); } - - /// Get a pointer to the implementation-pointer at the given index, - /// which must be in the range 0 .. getNumStubs() - 1. - void **getPtr(unsigned Idx) const { - char *PtrsBase = static_cast(StubsMem.base()) + NumStubs * StubSize; - return reinterpret_cast(PtrsBase) + Idx; - } - -private: - unsigned NumStubs = 0; - sys::OwningMemoryBlock StubsMem; }; class OrcAArch64 { public: - static const unsigned PointerSize = 8; - static const unsigned TrampolineSize = 12; - static const unsigned ResolverCodeSize = 0x120; - - using IndirectStubsInfo = GenericIndirectStubsInfo<8>; - - using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, - void *TrampolineId); + static constexpr unsigned PointerSize = 8; + static constexpr unsigned TrampolineSize = 12; + static constexpr unsigned StubSize = 8; + static constexpr unsigned StubToPointerMaxDisplacement = 1U << 27; + static constexpr unsigned ResolverCodeSize = 0x120; /// Write the resolver code into the given memory. The user is /// responsible for allocating the memory and setting permissions. - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, - void *CallbackMgr); + /// + /// ReentryFnAddr should be the address of a function whose signature matches + /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr + /// argument of writeResolverCode will be passed as the second argument to + /// the function at ReentryFnAddr. + static void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress RentryCtxAddr); /// Write the requested number of trampolines into the given memory, /// which must be big enough to hold 1 pointer, plus NumTrampolines /// trampolines. - static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, + static void writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, unsigned NumTrampolines); - /// Emit at least MinStubs worth of indirect call stubs, rounded out to - /// the nearest page size. - /// - /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k - /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513 - /// will return a block of 1024 (2-pages worth). - static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, void *InitialPtrVal); + /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. + /// Stubs will be written as if linked at StubsBlockTargetAddress, with the + /// Nth stub using the Nth pointer in memory starting at + /// PointersBlockTargetAddress. + static void writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned MinStubs); }; /// X86_64 code that's common to all ABIs. @@ -149,25 +129,26 @@ class OrcAArch64 { /// X86_64 supports lazy JITing. class OrcX86_64_Base { public: - static const unsigned PointerSize = 8; - static const unsigned TrampolineSize = 8; - - using IndirectStubsInfo = GenericIndirectStubsInfo<8>; + static constexpr unsigned PointerSize = 8; + static constexpr unsigned TrampolineSize = 8; + static constexpr unsigned StubSize = 8; + static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; /// Write the requested number of trampolines into the given memory, /// which must be big enough to hold 1 pointer, plus NumTrampolines /// trampolines. - static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, + static void writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, unsigned NumTrampolines); - /// Emit at least MinStubs worth of indirect call stubs, rounded out to - /// the nearest page size. - /// - /// E.g. Asking for 4 stubs on x86-64, where stubs are 8-bytes, with 4k - /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513 - /// will return a block of 1024 (2-pages worth). - static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, void *InitialPtrVal); + /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. + /// Stubs will be written as if linked at StubsBlockTargetAddress, with the + /// Nth stub using the Nth pointer in memory starting at + /// PointersBlockTargetAddress. + static void writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); }; /// X86_64 support for SysV ABI (Linux, MacOSX). @@ -175,15 +156,19 @@ class OrcX86_64_Base { /// X86_64_SysV supports lazy JITing. class OrcX86_64_SysV : public OrcX86_64_Base { public: - static const unsigned ResolverCodeSize = 0x6C; - - using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, - void *TrampolineId); + static constexpr unsigned ResolverCodeSize = 0x6C; /// Write the resolver code into the given memory. The user is /// responsible for allocating the memory and setting permissions. - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, - void *CallbackMgr); + /// + /// ReentryFnAddr should be the address of a function whose signature matches + /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr + /// argument of writeResolverCode will be passed as the second argument to + /// the function at ReentryFnAddr. + static void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr); }; /// X86_64 support for Win32. @@ -191,15 +176,19 @@ class OrcX86_64_SysV : public OrcX86_64_Base { /// X86_64_Win32 supports lazy JITing. class OrcX86_64_Win32 : public OrcX86_64_Base { public: - static const unsigned ResolverCodeSize = 0x74; - - using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, - void *TrampolineId); + static constexpr unsigned ResolverCodeSize = 0x74; /// Write the resolver code into the given memory. The user is /// responsible for allocating the memory and setting permissions. - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, - void *CallbackMgr); + /// + /// ReentryFnAddr should be the address of a function whose signature matches + /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr + /// argument of writeResolverCode will be passed as the second argument to + /// the function at ReentryFnAddr. + static void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr); }; /// I386 support. @@ -207,34 +196,39 @@ class OrcX86_64_Win32 : public OrcX86_64_Base { /// I386 supports lazy JITing. class OrcI386 { public: - static const unsigned PointerSize = 4; - static const unsigned TrampolineSize = 8; - static const unsigned ResolverCodeSize = 0x4a; - - using IndirectStubsInfo = GenericIndirectStubsInfo<8>; - - using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, - void *TrampolineId); + static constexpr unsigned PointerSize = 4; + static constexpr unsigned TrampolineSize = 8; + static constexpr unsigned StubSize = 8; + static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; + static constexpr unsigned ResolverCodeSize = 0x4a; /// Write the resolver code into the given memory. The user is /// responsible for allocating the memory and setting permissions. - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry, - void *CallbackMgr); + /// + /// ReentryFnAddr should be the address of a function whose signature matches + /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr + /// argument of writeResolverCode will be passed as the second argument to + /// the function at ReentryFnAddr. + static void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr); /// Write the requested number of trampolines into the given memory, /// which must be big enough to hold 1 pointer, plus NumTrampolines /// trampolines. - static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, + static void writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, unsigned NumTrampolines); - /// Emit at least MinStubs worth of indirect call stubs, rounded out to - /// the nearest page size. - /// - /// E.g. Asking for 4 stubs on i386, where stubs are 8-bytes, with 4k - /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513 - /// will return a block of 1024 (2-pages worth). - static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, void *InitialPtrVal); + /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. + /// Stubs will be written as if linked at StubsBlockTargetAddress, with the + /// Nth stub using the Nth pointer in memory starting at + /// PointersBlockTargetAddress. + static void writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); }; // @brief Mips32 support. @@ -242,41 +236,61 @@ class OrcI386 { // Mips32 supports lazy JITing. class OrcMips32_Base { public: - static const unsigned PointerSize = 4; - static const unsigned TrampolineSize = 20; - static const unsigned ResolverCodeSize = 0xfc; - using IndirectStubsInfo = GenericIndirectStubsInfo<16>; + static constexpr unsigned PointerSize = 4; + static constexpr unsigned TrampolineSize = 20; + static constexpr unsigned StubSize = 8; + static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; + static constexpr unsigned ResolverCodeSize = 0xfc; - using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, - void *TrampolineId); /// Write the requested number of trampolines into the given memory, /// which must be big enough to hold 1 pointer, plus NumTrampolines /// trampolines. - static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines); + static void writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, + unsigned NumTrampolines); /// Write the resolver code into the given memory. The user is /// responsible for allocating the memory and setting permissions. - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr, bool isBigEndian); - /// Emit at least MinStubs worth of indirect call stubs, rounded out to - /// the nearest page size. /// - /// E.g. Asking for 4 stubs on Mips32, where stubs are 8-bytes, with 4k - /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513 - /// will return a block of 1024 (2-pages worth). - static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal); + /// ReentryFnAddr should be the address of a function whose signature matches + /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr + /// argument of writeResolverCode will be passed as the second argument to + /// the function at ReentryFnAddr. + static void writeResolverCode(char *ResolverBlockWorkingMem, + JITTargetAddress ResolverBlockTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr, + bool isBigEndian); + /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. + /// Stubs will be written as if linked at StubsBlockTargetAddress, with the + /// Nth stub using the Nth pointer in memory starting at + /// PointersBlockTargetAddress. + static void writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); }; - class OrcMips32Le : public OrcMips32_Base { public: - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr) - { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, false); } + static void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) { + OrcMips32_Base::writeResolverCode(ResolverWorkingMem, ResolverTargetAddress, + ReentryFnAddr, ReentryCtxAddr, false); + } }; class OrcMips32Be : public OrcMips32_Base { public: - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr) - { OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, true); } + static void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) { + OrcMips32_Base::writeResolverCode(ResolverWorkingMem, ResolverTargetAddress, + ReentryFnAddr, ReentryCtxAddr, true); + } }; // @brief Mips64 support. @@ -284,31 +298,41 @@ class OrcMips32Be : public OrcMips32_Base { // Mips64 supports lazy JITing. class OrcMips64 { public: - static const unsigned PointerSize = 8; - static const unsigned TrampolineSize = 40; - static const unsigned ResolverCodeSize = 0x120; + static constexpr unsigned PointerSize = 8; + static constexpr unsigned TrampolineSize = 40; + static constexpr unsigned StubSize = 32; + static constexpr unsigned StubToPointerMaxDisplacement = 1 << 31; + static constexpr unsigned ResolverCodeSize = 0x120; - using IndirectStubsInfo = GenericIndirectStubsInfo<32>; - using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr, - void *TrampolineId); /// Write the resolver code into the given memory. The user is /// responsible for allocating the memory and setting permissions. - static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr); + /// + /// ReentryFnAddr should be the address of a function whose signature matches + /// void* (*)(void *TrampolineAddr, void *ReentryCtxAddr). The ReentryCtxAddr + /// argument of writeResolverCode will be passed as the second argument to + /// the function at ReentryFnAddr. + static void writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr); /// Write the requested number of trampolines into the given memory, /// which must be big enough to hold 1 pointer, plus NumTrampolines /// trampolines. - static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines); - - /// Emit at least MinStubs worth of indirect call stubs, rounded out to - /// the nearest page size. - /// - /// E.g. Asking for 4 stubs on Mips64, where stubs are 8-bytes, with 4k - /// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513 - /// will return a block of 1024 (2-pages worth). - static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal); + static void writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverFnAddr, + unsigned NumTrampolines); + /// Write NumStubs indirect stubs to working memory at StubsBlockWorkingMem. + /// Stubs will be written as if linked at StubsBlockTargetAddress, with the + /// Nth stub using the Nth pointer in memory starting at + /// PointersBlockTargetAddress. + static void writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs); }; - } // end namespace orc - } // end namespace llvm +} // end namespace orc +} // end namespace llvm + #endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h index ac1df847cf7e2..50c155d77db17 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h @@ -15,6 +15,7 @@ #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETSERVER_H #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h" #include "llvm/Support/Debug.h" @@ -262,19 +263,17 @@ class OrcRemoteTargetServer return errorCodeToError( orcError(OrcErrorCode::RemoteIndirectStubsOwnerDoesNotExist)); - typename TargetT::IndirectStubsInfo IS; - if (auto Err = - TargetT::emitIndirectStubsBlock(IS, NumStubsRequired, nullptr)) - return std::move(Err); + auto IS = LocalIndirectStubsInfo::create( + NumStubsRequired, sys::Process::getPageSizeEstimate()); + if (!IS) + return IS.takeError(); - JITTargetAddress StubsBase = static_cast( - reinterpret_cast(IS.getStub(0))); - JITTargetAddress PtrsBase = static_cast( - reinterpret_cast(IS.getPtr(0))); - uint32_t NumStubsEmitted = IS.getNumStubs(); + JITTargetAddress StubsBase = pointerToJITTargetAddress(IS->getStub(0)); + JITTargetAddress PtrsBase = pointerToJITTargetAddress(IS->getPtr(0)); + uint32_t NumStubsEmitted = IS->getNumStubs(); auto &BlockList = StubOwnerItr->second; - BlockList.push_back(std::move(IS)); + BlockList.push_back(std::move(*IS)); return std::make_tuple(StubsBase, PtrsBase, NumStubsEmitted); } @@ -287,8 +286,10 @@ class OrcRemoteTargetServer if (EC) return errorCodeToError(EC); - TargetT::writeResolverCode(static_cast(ResolverBlock.base()), - &reenter, this); + TargetT::writeResolverCode(static_cast(ResolverBlock.base()), + pointerToJITTargetAddress(ResolverBlock.base()), + pointerToJITTargetAddress(&reenter), + pointerToJITTargetAddress(this)); return errorCodeToError(sys::Memory::protectMappedMemory( ResolverBlock.getMemoryBlock(), @@ -308,9 +309,10 @@ class OrcRemoteTargetServer (sys::Process::getPageSizeEstimate() - TargetT::PointerSize) / TargetT::TrampolineSize; - uint8_t *TrampolineMem = static_cast(TrampolineBlock.base()); - TargetT::writeTrampolines(TrampolineMem, ResolverBlock.base(), - NumTrampolines); + char *TrampolineMem = static_cast(TrampolineBlock.base()); + TargetT::writeTrampolines( + TrampolineMem, pointerToJITTargetAddress(TrampolineMem), + pointerToJITTargetAddress(ResolverBlock.base()), NumTrampolines); EC = sys::Memory::protectMappedMemory(TrampolineBlock.getMemoryBlock(), sys::Memory::MF_READ | @@ -318,10 +320,8 @@ class OrcRemoteTargetServer TrampolineBlocks.push_back(std::move(TrampolineBlock)); - auto TrampolineBaseAddr = static_cast( - reinterpret_cast(TrampolineMem)); - - return std::make_tuple(TrampolineBaseAddr, NumTrampolines); + return std::make_tuple(pointerToJITTargetAddress(TrampolineMem), + NumTrampolines); } Expected handleGetSymbolAddress(const std::string &Name) { @@ -337,7 +337,7 @@ class OrcRemoteTargetServer uint32_t PointerSize = TargetT::PointerSize; uint32_t PageSize = sys::Process::getPageSizeEstimate(); uint32_t TrampolineSize = TargetT::TrampolineSize; - uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize; + uint32_t IndirectStubSize = TargetT::StubSize; LLVM_DEBUG(dbgs() << " Remote info:\n" << " triple = '" << ProcessTriple << "'\n" << " pointer size = " << PointerSize << "\n" @@ -433,7 +433,7 @@ class OrcRemoteTargetServer SymbolLookupFtor SymbolLookup; EHFrameRegistrationFtor EHFramesRegister, EHFramesDeregister; std::map Allocators; - using ISBlockOwnerList = std::vector; + using ISBlockOwnerList = std::vector>; std::map IndirectStubsOwners; sys::OwningMemoryBlock ResolverBlock; std::vector TrampolineBlocks; diff --git a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp index 8ed23de419d1e..5f89d91ef9948 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp @@ -7,13 +7,46 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Orc/OrcABISupport.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Process.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "orc" + +using namespace llvm; + +template +bool stubAndPointerRangesOk(JITTargetAddress StubBlockAddr, + JITTargetAddress PointerBlockAddr, + unsigned NumStubs) { + constexpr unsigned MaxDisp = ORCABI::StubToPointerMaxDisplacement; + JITTargetAddress FirstStub = StubBlockAddr; + JITTargetAddress LastStub = FirstStub + ((NumStubs - 1) * ORCABI::StubSize); + JITTargetAddress FirstPointer = PointerBlockAddr; + JITTargetAddress LastPointer = + FirstPointer + ((NumStubs - 1) * ORCABI::StubSize); + + if (FirstStub < FirstPointer) { + if (LastStub >= FirstPointer) + return false; // Ranges overlap. + return (FirstPointer - FirstStub <= MaxDisp) && + (LastPointer - LastStub <= MaxDisp); // out-of-range. + } + + if (LastPointer >= FirstStub) + return false; // Ranges overlap. + + return (FirstStub - FirstPointer <= MaxDisp) && + (LastStub - LastPointer <= MaxDisp); +} namespace llvm { namespace orc { -void OrcAArch64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, - void *CallbackMgr) { +void OrcAArch64::writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) { const uint32_t ResolverCode[] = { // resolver_entry: @@ -48,7 +81,7 @@ void OrcAArch64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, 0xadbf17e4, // 0x070: stp q4, q5, [sp, #-32]! 0xadbf0fe2, // 0x074: stp q2, q3, [sp, #-32]! 0xadbf07e0, // 0x078: stp q0, q1, [sp, #-32]! - 0x580004e0, // 0x07c: ldr x0, Lcallbackmgr + 0x580004e0, // 0x07c: ldr x0, Lreentry_ctx_ptr 0xaa1e03e1, // 0x080: mov x1, x30 0xd1003021, // 0x084: sub x1, x1, #12 0x58000442, // 0x088: ldr x2, Lreentry_fn_ptr @@ -87,43 +120,47 @@ void OrcAArch64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, 0xd65f0220, // 0x10c: ret x17 0x01234567, // 0x110: Lreentry_fn_ptr: 0xdeadbeef, // 0x114: .quad 0 - 0x98765432, // 0x118: Lcallbackmgr: + 0x98765432, // 0x118: Lreentry_ctx_ptr: 0xcafef00d // 0x11c: .quad 0 }; const unsigned ReentryFnAddrOffset = 0x110; - const unsigned CallbackMgrAddrOffset = 0x118; + const unsigned ReentryCtxAddrOffset = 0x118; - memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); - memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); - memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, - sizeof(CallbackMgr)); + memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr, + sizeof(uint64_t)); + memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr, + sizeof(uint64_t)); } -void OrcAArch64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, +void OrcAArch64::writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, unsigned NumTrampolines) { unsigned OffsetToPtr = alignTo(NumTrampolines * TrampolineSize, 8); - memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void *)); + memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr, + sizeof(uint64_t)); // OffsetToPtr is actually the offset from the PC for the 2nd instruction, so // subtract 32-bits. OffsetToPtr -= 4; - uint32_t *Trampolines = reinterpret_cast(TrampolineMem); + uint32_t *Trampolines = + reinterpret_cast(TrampolineBlockWorkingMem); for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) { Trampolines[3 * I + 0] = 0xaa1e03f1; // mov x17, x30 Trampolines[3 * I + 1] = 0x58000010 | (OffsetToPtr << 3); // adr x16, Lptr Trampolines[3 * I + 2] = 0xd63f0200; // blr x16 } - } -Error OrcAArch64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, - void *InitialPtrVal) { +void OrcAArch64::writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) { // Stub format is: // // .section __orc_stubs @@ -144,68 +181,41 @@ Error OrcAArch64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, // // ... - const unsigned StubSize = IndirectStubsInfo::StubSize; - - // Emit at least MinStubs, rounded up to fill the pages allocated. - static const unsigned PageSize = sys::Process::getPageSizeEstimate(); - unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; - unsigned NumStubs = (NumPages * PageSize) / StubSize; - - // Allocate memory for stubs and pointers in one call. - std::error_code EC; - auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - 2 * NumPages * PageSize, nullptr, - sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); - - if (EC) - return errorCodeToError(EC); - - // Create separate MemoryBlocks representing the stubs and pointers. - sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); - sys::MemoryBlock PtrsBlock(static_cast(StubsMem.base()) + - NumPages * PageSize, - NumPages * PageSize); - - // Populate the stubs page stubs and mark it executable. - uint64_t *Stub = reinterpret_cast(StubsBlock.base()); - uint64_t PtrOffsetField = static_cast(NumPages * PageSize) - << 3; + static_assert(StubSize == PointerSize, + "Pointer and stub size must match for algorithm below"); + assert(stubAndPointerRangesOk( + StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) && + "PointersBlock is out of range"); + uint64_t PtrDisplacement = + PointersBlockTargetAddress - StubsBlockTargetAddress; + uint64_t *Stub = reinterpret_cast(StubsBlockWorkingMem); + uint64_t PtrOffsetField = PtrDisplacement << 3; for (unsigned I = 0; I < NumStubs; ++I) Stub[I] = 0xd61f020058000010 | PtrOffsetField; - - if (auto EC = sys::Memory::protectMappedMemory( - StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) - return errorCodeToError(EC); - - // Initialize all pointers to point at FailureAddress. - void **Ptr = reinterpret_cast(PtrsBlock.base()); - for (unsigned I = 0; I < NumStubs; ++I) - Ptr[I] = InitialPtrVal; - - StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); - - return Error::success(); } -void OrcX86_64_Base::writeTrampolines(uint8_t *TrampolineMem, - void *ResolverAddr, - unsigned NumTrampolines) { +void OrcX86_64_Base::writeTrampolines( + char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, unsigned NumTrampolines) { unsigned OffsetToPtr = NumTrampolines * TrampolineSize; - memcpy(TrampolineMem + OffsetToPtr, &ResolverAddr, sizeof(void *)); + memcpy(TrampolineBlockWorkingMem + OffsetToPtr, &ResolverAddr, + sizeof(uint64_t)); - uint64_t *Trampolines = reinterpret_cast(TrampolineMem); + uint64_t *Trampolines = + reinterpret_cast(TrampolineBlockWorkingMem); uint64_t CallIndirPCRel = 0xf1c40000000015ff; for (unsigned I = 0; I < NumTrampolines; ++I, OffsetToPtr -= TrampolineSize) Trampolines[I] = CallIndirPCRel | ((OffsetToPtr - 6) << 16); } -Error OrcX86_64_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, - void *InitialPtrVal) { +void OrcX86_64_Base::writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) { // Stub format is: // // .section __orc_stubs @@ -226,52 +236,28 @@ Error OrcX86_64_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, // // ... - const unsigned StubSize = IndirectStubsInfo::StubSize; - - // Emit at least MinStubs, rounded up to fill the pages allocated. - static const unsigned PageSize = sys::Process::getPageSizeEstimate(); - unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; - unsigned NumStubs = (NumPages * PageSize) / StubSize; - - // Allocate memory for stubs and pointers in one call. - std::error_code EC; - auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - 2 * NumPages * PageSize, nullptr, - sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); - - if (EC) - return errorCodeToError(EC); - - // Create separate MemoryBlocks representing the stubs and pointers. - sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); - sys::MemoryBlock PtrsBlock(static_cast(StubsMem.base()) + - NumPages * PageSize, - NumPages * PageSize); - // Populate the stubs page stubs and mark it executable. - uint64_t *Stub = reinterpret_cast(StubsBlock.base()); - uint64_t PtrOffsetField = static_cast(NumPages * PageSize - 6) - << 16; + static_assert(StubSize == PointerSize, + "Pointer and stub size must match for algorithm below"); + assert(stubAndPointerRangesOk( + StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) && + "PointersBlock is out of range"); + uint64_t *Stub = reinterpret_cast(StubsBlockWorkingMem); + uint64_t PtrOffsetField = + (PointersBlockTargetAddress - StubsBlockTargetAddress - 6) << 16; for (unsigned I = 0; I < NumStubs; ++I) Stub[I] = 0xF1C40000000025ff | PtrOffsetField; - - if (auto EC = sys::Memory::protectMappedMemory( - StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) - return errorCodeToError(EC); - - // Initialize all pointers to point at FailureAddress. - void **Ptr = reinterpret_cast(PtrsBlock.base()); - for (unsigned I = 0; I < NumStubs; ++I) - Ptr[I] = InitialPtrVal; - - StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); - - return Error::success(); } -void OrcX86_64_SysV::writeResolverCode(uint8_t *ResolverMem, - JITReentryFn ReentryFn, - void *CallbackMgr) { +void OrcX86_64_SysV::writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) { + + LLVM_DEBUG({ + dbgs() << "Writing resolver code to " + << formatv("{0:x16}", ResolverTargetAddress) << "\n"; + }); const uint8_t ResolverCode[] = { // resolver_entry: @@ -295,7 +281,7 @@ void OrcX86_64_SysV::writeResolverCode(uint8_t *ResolverMem, 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp) 0x48, 0xbf, // 0x26: movabsq , %rdi - // 0x28: Callback manager addr. + // 0x28: JIT re-entry ctx addr. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x75, 0x08, // 0x30: movq 8(%rbp), %rsi @@ -325,23 +311,26 @@ void OrcX86_64_SysV::writeResolverCode(uint8_t *ResolverMem, 0x58, // 0x69: popq %rax 0x5d, // 0x6a: popq %rbp 0xc3, // 0x6b: retq - }; + }; const unsigned ReentryFnAddrOffset = 0x3a; - const unsigned CallbackMgrAddrOffset = 0x28; + const unsigned ReentryCtxAddrOffset = 0x28; - memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); - memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); - memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, - sizeof(CallbackMgr)); + memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr, + sizeof(uint64_t)); + memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr, + sizeof(uint64_t)); } -void OrcX86_64_Win32::writeResolverCode(uint8_t *ResolverMem, - JITReentryFn ReentryFn, - void *CallbackMgr) { +void OrcX86_64_Win32::writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) { - // resolverCode is similar to OrcX86_64 with differences specific to windows x64 calling convention: - // arguments go into rcx, rdx and come in reverse order, shadow space allocation on stack + // resolverCode is similar to OrcX86_64 with differences specific to windows + // x64 calling convention: arguments go into rcx, rdx and come in reverse + // order, shadow space allocation on stack const uint8_t ResolverCode[] = { // resolver_entry: 0x55, // 0x00: pushq %rbp @@ -364,7 +353,7 @@ void OrcX86_64_Win32::writeResolverCode(uint8_t *ResolverMem, 0x48, 0x0f, 0xae, 0x04, 0x24, // 0x21: fxsave64 (%rsp) 0x48, 0xb9, // 0x26: movabsq , %rcx - // 0x28: Callback manager addr. + // 0x28: JIT re-entry ctx addr. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x55, 0x08, // 0x30: mov rdx, [rbp+0x8] @@ -402,18 +391,23 @@ void OrcX86_64_Win32::writeResolverCode(uint8_t *ResolverMem, 0xc3, // 0x73: retq }; - const unsigned ReentryFnAddrOffset = 0x3a; - const unsigned CallbackMgrAddrOffset = 0x28; + const unsigned ReentryCtxAddrOffset = 0x28; - memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); - memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); - memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, - sizeof(CallbackMgr)); + memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr, + sizeof(uint64_t)); + memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr, + sizeof(uint64_t)); } -void OrcI386::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, - void *CallbackMgr) { +void OrcI386::writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) { + + assert((ReentryFnAddr >> 32) == 0 && "ReentryFnAddr out of range"); + assert((ReentryCtxAddr >> 32) == 0 && "ReentryCtxAddr out of range"); const uint8_t ResolverCode[] = { // resolver_entry: @@ -451,29 +445,39 @@ void OrcI386::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, }; const unsigned ReentryFnAddrOffset = 0x2a; - const unsigned CallbackMgrAddrOffset = 0x25; + const unsigned ReentryCtxAddrOffset = 0x25; - memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); - memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryFn, sizeof(ReentryFn)); - memcpy(ResolverMem + CallbackMgrAddrOffset, &CallbackMgr, - sizeof(CallbackMgr)); + memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnAddr, + sizeof(uint32_t)); + memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxAddr, + sizeof(uint32_t)); } -void OrcI386::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, +void OrcI386::writeTrampolines(char *TrampolineWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, unsigned NumTrampolines) { + assert((ResolverAddr >> 32) == 0 && "ResolverAddr out of range"); uint64_t CallRelImm = 0xF1C4C400000000e8; - uint64_t Resolver = reinterpret_cast(ResolverAddr); uint64_t ResolverRel = - Resolver - reinterpret_cast(TrampolineMem) - 5; + ResolverAddr - reinterpret_cast(TrampolineBlockTargetAddress) - + 5; - uint64_t *Trampolines = reinterpret_cast(TrampolineMem); + uint64_t *Trampolines = reinterpret_cast(TrampolineWorkingMem); for (unsigned I = 0; I < NumTrampolines; ++I, ResolverRel -= TrampolineSize) Trampolines[I] = CallRelImm | (ResolverRel << 8); } -Error OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, void *InitialPtrVal) { +void OrcI386::writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) { + assert((StubsBlockTargetAddress >> 32) == 0 && + "StubsBlockTargetAddress is out of range"); + assert((PointersBlockTargetAddress >> 32) == 0 && + "PointersBlockTargetAddress is out of range"); + // Stub format is: // // .section __orc_stubs @@ -494,51 +498,21 @@ Error OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, // // ... - const unsigned StubSize = IndirectStubsInfo::StubSize; + assert(stubAndPointerRangesOk( + StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) && + "PointersBlock is out of range"); - // Emit at least MinStubs, rounded up to fill the pages allocated. - static const unsigned PageSize = sys::Process::getPageSizeEstimate(); - unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; - unsigned NumStubs = (NumPages * PageSize) / StubSize; - - // Allocate memory for stubs and pointers in one call. - std::error_code EC; - auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - 2 * NumPages * PageSize, nullptr, - sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); - - if (EC) - return errorCodeToError(EC); - - // Create separate MemoryBlocks representing the stubs and pointers. - sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); - sys::MemoryBlock PtrsBlock(static_cast(StubsMem.base()) + - NumPages * PageSize, - NumPages * PageSize); - - // Populate the stubs page stubs and mark it executable. - uint64_t *Stub = reinterpret_cast(StubsBlock.base()); - uint64_t PtrAddr = reinterpret_cast(PtrsBlock.base()); + uint64_t *Stub = reinterpret_cast(StubsBlockWorkingMem); + uint64_t PtrAddr = PointersBlockTargetAddress; for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 4) Stub[I] = 0xF1C40000000025ff | (PtrAddr << 16); - - if (auto EC = sys::Memory::protectMappedMemory( - StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) - return errorCodeToError(EC); - - // Initialize all pointers to point at FailureAddress. - void **Ptr = reinterpret_cast(PtrsBlock.base()); - for (unsigned I = 0; I < NumStubs; ++I) - Ptr[I] = InitialPtrVal; - - StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); - - return Error::success(); } -void OrcMips32_Base::writeResolverCode(uint8_t *ResolverMem, - JITReentryFn ReentryFn, - void *CallbackMgr, bool isBigEndian) { +void OrcMips32_Base::writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr, + bool isBigEndian) { const uint32_t ResolverCode[] = { // resolver_entry: @@ -570,9 +544,9 @@ void OrcMips32_Base::writeResolverCode(uint8_t *ResolverMem, 0xafbe0060, // 0x64: sw $fp,96($sp) 0xafbf0064, // 0x68: sw $ra,100($sp) - // Callback manager addr. - 0x00000000, // 0x6c: lui $a0,callbackmgr - 0x00000000, // 0x70: addiu $a0,$a0,callbackmgr + // JIT re-entry ctx addr. + 0x00000000, // 0x6c: lui $a0,ctx + 0x00000000, // 0x70: addiu $a0,$a0,ctx 0x03e02825, // 0x74: move $a1, $ra 0x24a5ffec, // 0x78: addiu $a1,$a1,-20 @@ -614,50 +588,63 @@ void OrcMips32_Base::writeResolverCode(uint8_t *ResolverMem, }; const unsigned ReentryFnAddrOffset = 0x7c; // JIT re-entry fn addr lui - const unsigned CallbackMgrAddrOffset = 0x6c; // Callback manager addr lui + const unsigned ReentryCtxAddrOffset = 0x6c; // JIT re-entry context addr lui const unsigned Offsett = 0xf8; - memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); + memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode)); // Depending on endian return value will be in v0 or v1. uint32_t MoveVxT9 = isBigEndian ? 0x0060c825 : 0x0040c825; - memcpy(ResolverMem + Offsett, &MoveVxT9, sizeof(MoveVxT9)); - - uint64_t CallMgrAddr = reinterpret_cast(CallbackMgr); - uint32_t CallMgrLUi = 0x3c040000 | (((CallMgrAddr + 0x8000) >> 16) & 0xFFFF); - uint32_t CallMgrADDiu = 0x24840000 | ((CallMgrAddr) & 0xFFFF); - memcpy(ResolverMem + CallbackMgrAddrOffset, &CallMgrLUi, sizeof(CallMgrLUi)); - memcpy(ResolverMem + CallbackMgrAddrOffset + 4, &CallMgrADDiu, - sizeof(CallMgrADDiu)); - - uint64_t ReentryAddr = reinterpret_cast(ReentryFn); - uint32_t ReentryLUi = 0x3c190000 | (((ReentryAddr + 0x8000) >> 16) & 0xFFFF); - uint32_t ReentryADDiu = 0x27390000 | ((ReentryAddr) & 0xFFFF); - memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryLUi, sizeof(ReentryLUi)); - memcpy(ResolverMem + ReentryFnAddrOffset + 4, &ReentryADDiu, - sizeof(ReentryADDiu)); + memcpy(ResolverWorkingMem + Offsett, &MoveVxT9, sizeof(MoveVxT9)); + + uint32_t ReentryCtxLUi = + 0x3c040000 | (((ReentryCtxAddr + 0x8000) >> 16) & 0xFFFF); + uint32_t ReentryCtxADDiu = 0x24840000 | ((ReentryCtxAddr)&0xFFFF); + memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLUi, + sizeof(ReentryCtxLUi)); + memcpy(ResolverWorkingMem + ReentryCtxAddrOffset + 4, &ReentryCtxADDiu, + sizeof(ReentryCtxADDiu)); + + uint32_t ReentryFnLUi = + 0x3c190000 | (((ReentryFnAddr + 0x8000) >> 16) & 0xFFFF); + uint32_t ReentryFnADDiu = 0x27390000 | ((ReentryFnAddr)&0xFFFF); + memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnLUi, + sizeof(ReentryFnLUi)); + memcpy(ResolverWorkingMem + ReentryFnAddrOffset + 4, &ReentryFnADDiu, + sizeof(ReentryFnADDiu)); } -void OrcMips32_Base::writeTrampolines(uint8_t *TrampolineMem, - void *ResolverAddr, - unsigned NumTrampolines) { +void OrcMips32_Base::writeTrampolines( + char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, unsigned NumTrampolines) { - uint32_t *Trampolines = reinterpret_cast(TrampolineMem); - uint64_t ResolveAddr = reinterpret_cast(ResolverAddr); - uint32_t RHiAddr = ((ResolveAddr + 0x8000) >> 16); + assert((ResolverAddr >> 32) == 0 && "ResolverAddr out of range"); + + uint32_t *Trampolines = + reinterpret_cast(TrampolineBlockWorkingMem); + uint32_t RHiAddr = ((ResolverAddr + 0x8000) >> 16); for (unsigned I = 0; I < NumTrampolines; ++I) { - Trampolines[5 * I + 0] = 0x03e0c025; // move $t8,$ra - Trampolines[5 * I + 1] = 0x3c190000 | (RHiAddr & 0xFFFF); // lui $t9,resolveAddr - Trampolines[5 * I + 2] = 0x27390000 | (ResolveAddr & 0xFFFF); // addiu $t9,$t9,resolveAddr - Trampolines[5 * I + 3] = 0x0320f809; // jalr $t9 - Trampolines[5 * I + 4] = 0x00000000; // nop + // move $t8,$ra + // lui $t9,ResolverAddr + // addiu $t9,$t9,ResolverAddr + // jalr $t9 + // nop + Trampolines[5 * I + 0] = 0x03e0c025; + Trampolines[5 * I + 1] = 0x3c190000 | (RHiAddr & 0xFFFF); + Trampolines[5 * I + 2] = 0x27390000 | (ResolverAddr & 0xFFFF); + Trampolines[5 * I + 3] = 0x0320f809; + Trampolines[5 * I + 4] = 0x00000000; } } -Error OrcMips32_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, - void *InitialPtrVal) { +void OrcMips32_Base::writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) { + assert((StubsBlockTargetAddress >> 32) == 0 && + "InitialPtrVal is out of range"); + // Stub format is: // // .section __orc_stubs @@ -678,33 +665,15 @@ Error OrcMips32_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, // ptr2: // .word 0x0 // - // ... - - const unsigned StubSize = IndirectStubsInfo::StubSize; - - // Emit at least MinStubs, rounded up to fill the pages allocated. - static const unsigned PageSize = sys::Process::getPageSizeEstimate(); - unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; - unsigned NumStubs = (NumPages * PageSize) / StubSize; + // i.. - // Allocate memory for stubs and pointers in one call. - std::error_code EC; - auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - 2 * NumPages * PageSize, nullptr, - sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); - - if (EC) - return errorCodeToError(EC); - - // Create separate MemoryBlocks representing the stubs and pointers. - sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); - sys::MemoryBlock PtrsBlock(static_cast(StubsMem.base()) + - NumPages * PageSize, - NumPages * PageSize); + assert(stubAndPointerRangesOk( + StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) && + "PointersBlock is out of range"); // Populate the stubs page stubs and mark it executable. - uint32_t *Stub = reinterpret_cast(StubsBlock.base()); - uint64_t PtrAddr = reinterpret_cast(Stub) + NumPages * PageSize; + uint32_t *Stub = reinterpret_cast(StubsBlockWorkingMem); + uint64_t PtrAddr = PointersBlockTargetAddress; for (unsigned I = 0; I < NumStubs; ++I) { uint32_t HiAddr = ((PtrAddr + 0x8000) >> 16); @@ -714,26 +683,15 @@ Error OrcMips32_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, Stub[4 * I + 3] = 0x00000000; // nop PtrAddr += 4; } - - if (auto EC = sys::Memory::protectMappedMemory( - StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) - return errorCodeToError(EC); - - // Initialize all pointers to point at FailureAddress. - void **Ptr = reinterpret_cast(PtrsBlock.base()); - for (unsigned I = 0; I < NumStubs; ++I) - Ptr[I] = InitialPtrVal; - - StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); - - return Error::success(); } -void OrcMips64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, - void *CallbackMgr) { +void OrcMips64::writeResolverCode(char *ResolverWorkingMem, + JITTargetAddress ResolverTargetAddress, + JITTargetAddress ReentryFnAddr, + JITTargetAddress ReentryCtxAddr) { const uint32_t ResolverCode[] = { - //resolver_entry: + //resolver_entry: 0x67bdff30, // 0x00: daddiu $sp,$sp,-208 0xffa20000, // 0x04: sd v0,0(sp) 0xffa30008, // 0x08: sd v1,8(sp) @@ -762,13 +720,13 @@ void OrcMips64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, 0xffbe00c0, // 0x64: sd fp,192(sp) 0xffbf00c8, // 0x68: sd ra,200(sp) - // Callback manager addr. - 0x00000000, // 0x6c: lui $a0,heighest(callbackmgr) - 0x00000000, // 0x70: daddiu $a0,$a0,heigher(callbackmgr) + // JIT re-entry ctx addr. + 0x00000000, // 0x6c: lui $a0,heighest(ctx) + 0x00000000, // 0x70: daddiu $a0,$a0,heigher(ctx) 0x00000000, // 0x74: dsll $a0,$a0,16 - 0x00000000, // 0x78: daddiu $a0,$a0,hi(callbackmgr) + 0x00000000, // 0x78: daddiu $a0,$a0,hi(ctx) 0x00000000, // 0x7c: dsll $a0,$a0,16 - 0x00000000, // 0x80: daddiu $a0,$a0,lo(callbackmgr) + 0x00000000, // 0x80: daddiu $a0,$a0,lo(ctx) 0x03e02825, // 0x84: move $a1, $ra 0x64a5ffdc, // 0x88: daddiu $a1,$a1,-36 @@ -814,73 +772,73 @@ void OrcMips64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn, }; const unsigned ReentryFnAddrOffset = 0x8c; // JIT re-entry fn addr lui - const unsigned CallbackMgrAddrOffset = 0x6c; // Callback manager addr lui - - memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode)); - - uint64_t CallMgrAddr = reinterpret_cast(CallbackMgr); - - uint32_t CallMgrLUi = - 0x3c040000 | (((CallMgrAddr + 0x800080008000) >> 48) & 0xFFFF); - uint32_t CallMgrDADDiu = - 0x64840000 | (((CallMgrAddr + 0x80008000) >> 32) & 0xFFFF); - uint32_t CallMgrDSLL = 0x00042438; - uint32_t CallMgrDADDiu2 = - 0x64840000 | ((((CallMgrAddr + 0x8000) >> 16) & 0xFFFF)); - uint32_t CallMgrDSLL2 = 0x00042438; - uint32_t CallMgrDADDiu3 = 0x64840000 | ((CallMgrAddr)&0xFFFF); - - memcpy(ResolverMem + CallbackMgrAddrOffset, &CallMgrLUi, sizeof(CallMgrLUi)); - memcpy(ResolverMem + (CallbackMgrAddrOffset + 4), &CallMgrDADDiu, - sizeof(CallMgrDADDiu)); - memcpy(ResolverMem + (CallbackMgrAddrOffset + 8), &CallMgrDSLL, - sizeof(CallMgrDSLL)); - memcpy(ResolverMem + (CallbackMgrAddrOffset + 12), &CallMgrDADDiu2, - sizeof(CallMgrDADDiu2)); - memcpy(ResolverMem + (CallbackMgrAddrOffset + 16), &CallMgrDSLL2, - sizeof(CallMgrDSLL2)); - memcpy(ResolverMem + (CallbackMgrAddrOffset + 20), &CallMgrDADDiu3, - sizeof(CallMgrDADDiu3)); - - uint64_t ReentryAddr = reinterpret_cast(ReentryFn); - - uint32_t ReentryLUi = - 0x3c190000 | (((ReentryAddr + 0x800080008000) >> 48) & 0xFFFF); - - uint32_t ReentryDADDiu = - 0x67390000 | (((ReentryAddr + 0x80008000) >> 32) & 0xFFFF); - - uint32_t ReentryDSLL = 0x0019cc38; - - uint32_t ReentryDADDiu2 = - 0x67390000 | (((ReentryAddr + 0x8000) >> 16) & 0xFFFF); - - uint32_t ReentryDSLL2 = 0x0019cc38; - - uint32_t ReentryDADDiu3 = 0x67390000 | ((ReentryAddr)&0xFFFF); - - memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryLUi, sizeof(ReentryLUi)); - memcpy(ResolverMem + (ReentryFnAddrOffset + 4), &ReentryDADDiu, - sizeof(ReentryDADDiu)); - memcpy(ResolverMem + (ReentryFnAddrOffset + 8), &ReentryDSLL, - sizeof(ReentryDSLL)); - memcpy(ResolverMem + (ReentryFnAddrOffset + 12), &ReentryDADDiu2, - sizeof(ReentryDADDiu2)); - memcpy(ResolverMem + (ReentryFnAddrOffset + 16), &ReentryDSLL2, - sizeof(ReentryDSLL2)); - memcpy(ResolverMem + (ReentryFnAddrOffset + 20), &ReentryDADDiu3, - sizeof(ReentryDADDiu3)); + const unsigned ReentryCtxAddrOffset = 0x6c; // JIT re-entry ctx addr lui + + memcpy(ResolverWorkingMem, ResolverCode, sizeof(ResolverCode)); + + uint32_t ReentryCtxLUi = + 0x3c040000 | (((ReentryCtxAddr + 0x800080008000) >> 48) & 0xFFFF); + uint32_t ReentryCtxDADDiu = + 0x64840000 | (((ReentryCtxAddr + 0x80008000) >> 32) & 0xFFFF); + uint32_t ReentryCtxDSLL = 0x00042438; + uint32_t ReentryCtxDADDiu2 = + 0x64840000 | ((((ReentryCtxAddr + 0x8000) >> 16) & 0xFFFF)); + uint32_t ReentryCtxDSLL2 = 0x00042438; + uint32_t ReentryCtxDADDiu3 = 0x64840000 | ((ReentryCtxAddr)&0xFFFF); + + memcpy(ResolverWorkingMem + ReentryCtxAddrOffset, &ReentryCtxLUi, + sizeof(ReentryCtxLUi)); + memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 4), &ReentryCtxDADDiu, + sizeof(ReentryCtxDADDiu)); + memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 8), &ReentryCtxDSLL, + sizeof(ReentryCtxDSLL)); + memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 12), &ReentryCtxDADDiu2, + sizeof(ReentryCtxDADDiu2)); + memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 16), &ReentryCtxDSLL2, + sizeof(ReentryCtxDSLL2)); + memcpy(ResolverWorkingMem + (ReentryCtxAddrOffset + 20), &ReentryCtxDADDiu3, + sizeof(ReentryCtxDADDiu3)); + + uint32_t ReentryFnLUi = + 0x3c190000 | (((ReentryFnAddr + 0x800080008000) >> 48) & 0xFFFF); + + uint32_t ReentryFnDADDiu = + 0x67390000 | (((ReentryFnAddr + 0x80008000) >> 32) & 0xFFFF); + + uint32_t ReentryFnDSLL = 0x0019cc38; + + uint32_t ReentryFnDADDiu2 = + 0x67390000 | (((ReentryFnAddr + 0x8000) >> 16) & 0xFFFF); + + uint32_t ReentryFnDSLL2 = 0x0019cc38; + + uint32_t ReentryFnDADDiu3 = 0x67390000 | ((ReentryFnAddr)&0xFFFF); + + memcpy(ResolverWorkingMem + ReentryFnAddrOffset, &ReentryFnLUi, + sizeof(ReentryFnLUi)); + memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 4), &ReentryFnDADDiu, + sizeof(ReentryFnDADDiu)); + memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 8), &ReentryFnDSLL, + sizeof(ReentryFnDSLL)); + memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 12), &ReentryFnDADDiu2, + sizeof(ReentryFnDADDiu2)); + memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 16), &ReentryFnDSLL2, + sizeof(ReentryFnDSLL2)); + memcpy(ResolverWorkingMem + (ReentryFnAddrOffset + 20), &ReentryFnDADDiu3, + sizeof(ReentryFnDADDiu3)); } -void OrcMips64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, +void OrcMips64::writeTrampolines(char *TrampolineBlockWorkingMem, + JITTargetAddress TrampolineBlockTargetAddress, + JITTargetAddress ResolverAddr, unsigned NumTrampolines) { - uint32_t *Trampolines = reinterpret_cast(TrampolineMem); - uint64_t ResolveAddr = reinterpret_cast(ResolverAddr); + uint32_t *Trampolines = + reinterpret_cast(TrampolineBlockWorkingMem); - uint64_t HeighestAddr = ((ResolveAddr + 0x800080008000) >> 48); - uint64_t HeigherAddr = ((ResolveAddr + 0x80008000) >> 32); - uint64_t HiAddr = ((ResolveAddr + 0x8000) >> 16); + uint64_t HeighestAddr = ((ResolverAddr + 0x800080008000) >> 48); + uint64_t HeigherAddr = ((ResolverAddr + 0x80008000) >> 32); + uint64_t HiAddr = ((ResolverAddr + 0x8000) >> 16); for (unsigned I = 0; I < NumTrampolines; ++I) { Trampolines[10 * I + 0] = 0x03e0c025; // move $t8,$ra @@ -889,16 +847,17 @@ void OrcMips64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr, Trampolines[10 * I + 3] = 0x0019cc38; // dsll $t9,$t9,16 Trampolines[10 * I + 4] = 0x67390000 | (HiAddr & 0xFFFF); // daddiu $t9,$t9,%hi(ptr) Trampolines[10 * I + 5] = 0x0019cc38; // dsll $t9,$t9,16 - Trampolines[10 * I + 6] = 0x67390000 | (ResolveAddr & 0xFFFF); // daddiu $t9,$t9,%lo(ptr) + Trampolines[10 * I + 6] = + 0x67390000 | (ResolverAddr & 0xFFFF); // daddiu $t9,$t9,%lo(ptr) Trampolines[10 * I + 7] = 0x0320f809; // jalr $t9 Trampolines[10 * I + 8] = 0x00000000; // nop Trampolines[10 * I + 9] = 0x00000000; // nop } } -Error OrcMips64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, - unsigned MinStubs, - void *InitialPtrVal) { +void OrcMips64::writeIndirectStubsBlock( + char *StubsBlockWorkingMem, JITTargetAddress StubsBlockTargetAddress, + JITTargetAddress PointersBlockTargetAddress, unsigned NumStubs) { // Stub format is: // // .section __orc_stubs @@ -926,31 +885,14 @@ Error OrcMips64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, // .dword 0x0 // // ... - const unsigned StubSize = IndirectStubsInfo::StubSize; - - // Emit at least MinStubs, rounded up to fill the pages allocated. - static const unsigned PageSize = sys::Process::getPageSizeEstimate(); - unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize; - unsigned NumStubs = (NumPages * PageSize) / StubSize; - // Allocate memory for stubs and pointers in one call. - std::error_code EC; - auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory( - 2 * NumPages * PageSize, nullptr, - sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC)); - - if (EC) - return errorCodeToError(EC); - - // Create separate MemoryBlocks representing the stubs and pointers. - sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize); - sys::MemoryBlock PtrsBlock(static_cast(StubsMem.base()) + - NumPages * PageSize, - NumPages * PageSize); + assert(stubAndPointerRangesOk( + StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) && + "PointersBlock is out of range"); // Populate the stubs page stubs and mark it executable. - uint32_t *Stub = reinterpret_cast(StubsBlock.base()); - uint64_t PtrAddr = reinterpret_cast(PtrsBlock.base()); + uint32_t *Stub = reinterpret_cast(StubsBlockWorkingMem); + uint64_t PtrAddr = PointersBlockTargetAddress; for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 8) { uint64_t HeighestAddr = ((PtrAddr + 0x800080008000) >> 48); @@ -965,19 +907,6 @@ Error OrcMips64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo, Stub[8 * I + 6] = 0x03200008; // jr $t9 Stub[8 * I + 7] = 0x00000000; // nop } - - if (auto EC = sys::Memory::protectMappedMemory( - StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC)) - return errorCodeToError(EC); - - // Initialize all pointers to point at FailureAddress. - void **Ptr = reinterpret_cast(PtrsBlock.base()); - for (unsigned I = 0; I < NumStubs; ++I) - Ptr[I] = InitialPtrVal; - - StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem)); - - return Error::success(); } } // End namespace orc. } // End namespace llvm. From 44899ed659ea55121059666841087f23c8880154 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 13 Jul 2020 17:19:05 +0000 Subject: [PATCH 121/771] [gn build] Port 83080a294ad --- llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn | 1 + llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn | 1 + 2 files changed, 2 insertions(+) diff --git a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn index 11498ed602984..c13dc723ecd1b 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn @@ -55,6 +55,7 @@ static_library("Analysis") { "InlineAdvisor.cpp", "InlineCost.cpp", "InlineFeaturesAnalysis.cpp", + "InlineSizeEstimatorAnalysis.cpp", "InstCount.cpp", "InstructionPrecedenceTracking.cpp", "InstructionSimplify.cpp", diff --git a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn index b0dcd497d844e..27733f63c2c50 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn @@ -25,6 +25,7 @@ unittest("AnalysisTests") { "GlobalsModRefTest.cpp", "IVDescriptorsTest.cpp", "InlineFeaturesAnalysisTest.cpp", + "InlineSizeEstimatorAnalysisTest.cpp", "LazyCallGraphTest.cpp", "LoadsTest.cpp", "LoopInfoTest.cpp", From fb558ccae743ed451ea42a30e197eb765a3184ac Mon Sep 17 00:00:00 2001 From: Hiroshi Yamauchi Date: Tue, 7 Jul 2020 11:01:35 -0700 Subject: [PATCH 122/771] [PGO][PGSO] Add profile guided size optimization to X86ISelDAGToDAG. Differential Revision: https://reviews.llvm.org/D83331 --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 10 +- llvm/test/CodeGen/X86/popcnt.ll | 446 ++++++++++++++++++++++++ llvm/test/CodeGen/X86/pr27202.ll | 30 ++ 3 files changed, 479 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index fb285376c5808..e91828bd17078 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -160,10 +160,6 @@ namespace { /// make the right decision when generating code for different targets. const X86Subtarget *Subtarget; - /// If true, selector should try to optimize for code size instead of - /// performance. - bool OptForSize; - /// If true, selector should try to optimize for minimum code size. bool OptForMinSize; @@ -172,7 +168,7 @@ namespace { public: explicit X86DAGToDAGISel(X86TargetMachine &tm, CodeGenOpt::Level OptLevel) - : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr), OptForSize(false), + : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr), OptForMinSize(false), IndirectTlsSegRefs(false) {} StringRef getPassName() const override { @@ -186,7 +182,7 @@ namespace { "indirect-tls-seg-refs"); // OptFor[Min]Size are used in pattern predicates that isel is matching. - OptForSize = MF.getFunction().hasOptSize(); + bool OptForSize = MF.getFunction().hasOptSize(); OptForMinSize = MF.getFunction().hasMinSize(); assert((!OptForMinSize || OptForSize) && "OptForMinSize implies OptForSize"); @@ -4557,7 +4553,7 @@ void X86DAGToDAGISel::Select(SDNode *Node) { // the patterns on the add/sub/and/or/xor with immediate paterns in the // tablegen files to check immediate use count without making the patterns // unavailable to the fast-isel table. - if (!OptForSize) + if (!CurDAG->shouldOptForSize()) break; // Only handle i8/i16/i32/i64. diff --git a/llvm/test/CodeGen/X86/popcnt.ll b/llvm/test/CodeGen/X86/popcnt.ll index c68a3a5fe3246..cc6f3153d2ca1 100644 --- a/llvm/test/CodeGen/X86/popcnt.ll +++ b/llvm/test/CodeGen/X86/popcnt.ll @@ -1034,8 +1034,454 @@ define i128 @cnt128_optsize(i128 %x) nounwind readnone optsize { ret i128 %cnt } +define i32 @cnt32_pgso(i32 %x) nounwind readnone !prof !14 { +; X32-LABEL: cnt32_pgso: +; X32: # %bb.0: +; X32-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-NEXT: movl %eax, %ecx +; X32-NEXT: shrl %ecx +; X32-NEXT: andl $1431655765, %ecx # imm = 0x55555555 +; X32-NEXT: subl %ecx, %eax +; X32-NEXT: movl $858993459, %ecx # imm = 0x33333333 +; X32-NEXT: movl %eax, %edx +; X32-NEXT: andl %ecx, %edx +; X32-NEXT: shrl $2, %eax +; X32-NEXT: andl %ecx, %eax +; X32-NEXT: addl %edx, %eax +; X32-NEXT: movl %eax, %ecx +; X32-NEXT: shrl $4, %ecx +; X32-NEXT: addl %eax, %ecx +; X32-NEXT: andl $252645135, %ecx # imm = 0xF0F0F0F +; X32-NEXT: imull $16843009, %ecx, %eax # imm = 0x1010101 +; X32-NEXT: shrl $24, %eax +; X32-NEXT: retl +; +; X64-LABEL: cnt32_pgso: +; X64: # %bb.0: +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shrl %eax +; X64-NEXT: andl $1431655765, %eax # imm = 0x55555555 +; X64-NEXT: subl %eax, %edi +; X64-NEXT: movl $858993459, %eax # imm = 0x33333333 +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: andl %eax, %ecx +; X64-NEXT: shrl $2, %edi +; X64-NEXT: andl %eax, %edi +; X64-NEXT: addl %ecx, %edi +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shrl $4, %eax +; X64-NEXT: addl %edi, %eax +; X64-NEXT: andl $252645135, %eax # imm = 0xF0F0F0F +; X64-NEXT: imull $16843009, %eax, %eax # imm = 0x1010101 +; X64-NEXT: shrl $24, %eax +; X64-NEXT: retq +; +; X32-POPCNT-LABEL: cnt32_pgso: +; X32-POPCNT: # %bb.0: +; X32-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %eax +; X32-POPCNT-NEXT: retl +; +; X64-POPCNT-LABEL: cnt32_pgso: +; X64-POPCNT: # %bb.0: +; X64-POPCNT-NEXT: popcntl %edi, %eax +; X64-POPCNT-NEXT: retq + %cnt = tail call i32 @llvm.ctpop.i32(i32 %x) + ret i32 %cnt +} + +define i64 @cnt64_pgso(i64 %x) nounwind readnone !prof !14 { +; X32-NOSSE-LABEL: cnt64_pgso: +; X32-NOSSE: # %bb.0: +; X32-NOSSE-NEXT: pushl %ebx +; X32-NOSSE-NEXT: pushl %edi +; X32-NOSSE-NEXT: pushl %esi +; X32-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X32-NOSSE-NEXT: movl %ecx, %edx +; X32-NOSSE-NEXT: shrl %edx +; X32-NOSSE-NEXT: movl $1431655765, %esi # imm = 0x55555555 +; X32-NOSSE-NEXT: andl %esi, %edx +; X32-NOSSE-NEXT: subl %edx, %ecx +; X32-NOSSE-NEXT: movl $858993459, %edx # imm = 0x33333333 +; X32-NOSSE-NEXT: movl %ecx, %edi +; X32-NOSSE-NEXT: andl %edx, %edi +; X32-NOSSE-NEXT: shrl $2, %ecx +; X32-NOSSE-NEXT: andl %edx, %ecx +; X32-NOSSE-NEXT: addl %edi, %ecx +; X32-NOSSE-NEXT: movl %ecx, %edi +; X32-NOSSE-NEXT: shrl $4, %edi +; X32-NOSSE-NEXT: addl %ecx, %edi +; X32-NOSSE-NEXT: movl $252645135, %ecx # imm = 0xF0F0F0F +; X32-NOSSE-NEXT: andl %ecx, %edi +; X32-NOSSE-NEXT: imull $16843009, %edi, %edi # imm = 0x1010101 +; X32-NOSSE-NEXT: shrl $24, %edi +; X32-NOSSE-NEXT: movl %eax, %ebx +; X32-NOSSE-NEXT: shrl %ebx +; X32-NOSSE-NEXT: andl %esi, %ebx +; X32-NOSSE-NEXT: subl %ebx, %eax +; X32-NOSSE-NEXT: movl %eax, %esi +; X32-NOSSE-NEXT: andl %edx, %esi +; X32-NOSSE-NEXT: shrl $2, %eax +; X32-NOSSE-NEXT: andl %edx, %eax +; X32-NOSSE-NEXT: addl %esi, %eax +; X32-NOSSE-NEXT: movl %eax, %edx +; X32-NOSSE-NEXT: shrl $4, %edx +; X32-NOSSE-NEXT: addl %eax, %edx +; X32-NOSSE-NEXT: andl %ecx, %edx +; X32-NOSSE-NEXT: imull $16843009, %edx, %eax # imm = 0x1010101 +; X32-NOSSE-NEXT: shrl $24, %eax +; X32-NOSSE-NEXT: addl %edi, %eax +; X32-NOSSE-NEXT: xorl %edx, %edx +; X32-NOSSE-NEXT: popl %esi +; X32-NOSSE-NEXT: popl %edi +; X32-NOSSE-NEXT: popl %ebx +; X32-NOSSE-NEXT: retl +; +; X64-LABEL: cnt64_pgso: +; X64: # %bb.0: +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrq %rax +; X64-NEXT: movabsq $6148914691236517205, %rcx # imm = 0x5555555555555555 +; X64-NEXT: andq %rax, %rcx +; X64-NEXT: subq %rcx, %rdi +; X64-NEXT: movabsq $3689348814741910323, %rax # imm = 0x3333333333333333 +; X64-NEXT: movq %rdi, %rcx +; X64-NEXT: andq %rax, %rcx +; X64-NEXT: shrq $2, %rdi +; X64-NEXT: andq %rax, %rdi +; X64-NEXT: addq %rcx, %rdi +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrq $4, %rax +; X64-NEXT: addq %rdi, %rax +; X64-NEXT: movabsq $1085102592571150095, %rcx # imm = 0xF0F0F0F0F0F0F0F +; X64-NEXT: andq %rax, %rcx +; X64-NEXT: movabsq $72340172838076673, %rax # imm = 0x101010101010101 +; X64-NEXT: imulq %rcx, %rax +; X64-NEXT: shrq $56, %rax +; X64-NEXT: retq +; +; X32-POPCNT-LABEL: cnt64_pgso: +; X32-POPCNT: # %bb.0: +; X32-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx +; X32-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %eax +; X32-POPCNT-NEXT: addl %ecx, %eax +; X32-POPCNT-NEXT: xorl %edx, %edx +; X32-POPCNT-NEXT: retl +; +; X64-POPCNT-LABEL: cnt64_pgso: +; X64-POPCNT: # %bb.0: +; X64-POPCNT-NEXT: popcntq %rdi, %rax +; X64-POPCNT-NEXT: retq +; +; X32-SSE2-LABEL: cnt64_pgso: +; X32-SSE2: # %bb.0: +; X32-SSE2-NEXT: movq {{.*#+}} xmm0 = mem[0],zero +; X32-SSE2-NEXT: movdqa %xmm0, %xmm1 +; X32-SSE2-NEXT: psrlw $1, %xmm1 +; X32-SSE2-NEXT: pand {{\.LCPI.*}}, %xmm1 +; X32-SSE2-NEXT: psubb %xmm1, %xmm0 +; X32-SSE2-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] +; X32-SSE2-NEXT: movdqa %xmm0, %xmm2 +; X32-SSE2-NEXT: pand %xmm1, %xmm2 +; X32-SSE2-NEXT: psrlw $2, %xmm0 +; X32-SSE2-NEXT: pand %xmm1, %xmm0 +; X32-SSE2-NEXT: paddb %xmm2, %xmm0 +; X32-SSE2-NEXT: movdqa %xmm0, %xmm1 +; X32-SSE2-NEXT: psrlw $4, %xmm1 +; X32-SSE2-NEXT: paddb %xmm0, %xmm1 +; X32-SSE2-NEXT: pand {{\.LCPI.*}}, %xmm1 +; X32-SSE2-NEXT: pxor %xmm0, %xmm0 +; X32-SSE2-NEXT: psadbw %xmm1, %xmm0 +; X32-SSE2-NEXT: movd %xmm0, %eax +; X32-SSE2-NEXT: xorl %edx, %edx +; X32-SSE2-NEXT: retl +; +; X32-SSSE3-LABEL: cnt64_pgso: +; X32-SSSE3: # %bb.0: +; X32-SSSE3-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; X32-SSSE3-NEXT: movq {{.*#+}} xmm1 = mem[0],zero +; X32-SSSE3-NEXT: movdqa %xmm1, %xmm2 +; X32-SSSE3-NEXT: pand %xmm0, %xmm2 +; X32-SSSE3-NEXT: movdqa {{.*#+}} xmm3 = [0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4] +; X32-SSSE3-NEXT: movdqa %xmm3, %xmm4 +; X32-SSSE3-NEXT: pshufb %xmm2, %xmm4 +; X32-SSSE3-NEXT: psrlw $4, %xmm1 +; X32-SSSE3-NEXT: pand %xmm0, %xmm1 +; X32-SSSE3-NEXT: pshufb %xmm1, %xmm3 +; X32-SSSE3-NEXT: paddb %xmm4, %xmm3 +; X32-SSSE3-NEXT: pxor %xmm0, %xmm0 +; X32-SSSE3-NEXT: psadbw %xmm3, %xmm0 +; X32-SSSE3-NEXT: movd %xmm0, %eax +; X32-SSSE3-NEXT: xorl %edx, %edx +; X32-SSSE3-NEXT: retl + %cnt = tail call i64 @llvm.ctpop.i64(i64 %x) + ret i64 %cnt +} + +define i128 @cnt128_pgso(i128 %x) nounwind readnone !prof !14 { +; X32-NOSSE-LABEL: cnt128_pgso: +; X32-NOSSE: # %bb.0: +; X32-NOSSE-NEXT: pushl %ebp +; X32-NOSSE-NEXT: pushl %ebx +; X32-NOSSE-NEXT: pushl %edi +; X32-NOSSE-NEXT: pushl %esi +; X32-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %edx +; X32-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %esi +; X32-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %ebx +; X32-NOSSE-NEXT: movl %ebx, %ecx +; X32-NOSSE-NEXT: shrl %ecx +; X32-NOSSE-NEXT: movl $1431655765, %edi # imm = 0x55555555 +; X32-NOSSE-NEXT: andl %edi, %ecx +; X32-NOSSE-NEXT: movl $1431655765, %edi # imm = 0x55555555 +; X32-NOSSE-NEXT: subl %ecx, %ebx +; X32-NOSSE-NEXT: movl $858993459, %ecx # imm = 0x33333333 +; X32-NOSSE-NEXT: movl %ebx, %ebp +; X32-NOSSE-NEXT: andl %ecx, %ebp +; X32-NOSSE-NEXT: shrl $2, %ebx +; X32-NOSSE-NEXT: andl %ecx, %ebx +; X32-NOSSE-NEXT: addl %ebp, %ebx +; X32-NOSSE-NEXT: movl %ebx, %ebp +; X32-NOSSE-NEXT: shrl $4, %ebp +; X32-NOSSE-NEXT: addl %ebx, %ebp +; X32-NOSSE-NEXT: movl %eax, %ebx +; X32-NOSSE-NEXT: shrl %ebx +; X32-NOSSE-NEXT: andl %edi, %ebx +; X32-NOSSE-NEXT: subl %ebx, %eax +; X32-NOSSE-NEXT: movl %eax, %ebx +; X32-NOSSE-NEXT: andl %ecx, %ebx +; X32-NOSSE-NEXT: shrl $2, %eax +; X32-NOSSE-NEXT: andl %ecx, %eax +; X32-NOSSE-NEXT: addl %ebx, %eax +; X32-NOSSE-NEXT: movl %eax, %edi +; X32-NOSSE-NEXT: shrl $4, %edi +; X32-NOSSE-NEXT: addl %eax, %edi +; X32-NOSSE-NEXT: movl $252645135, %ebx # imm = 0xF0F0F0F +; X32-NOSSE-NEXT: andl %ebx, %ebp +; X32-NOSSE-NEXT: imull $16843009, %ebp, %eax # imm = 0x1010101 +; X32-NOSSE-NEXT: shrl $24, %eax +; X32-NOSSE-NEXT: andl %ebx, %edi +; X32-NOSSE-NEXT: imull $16843009, %edi, %edi # imm = 0x1010101 +; X32-NOSSE-NEXT: shrl $24, %edi +; X32-NOSSE-NEXT: addl %eax, %edi +; X32-NOSSE-NEXT: movl %esi, %eax +; X32-NOSSE-NEXT: shrl %eax +; X32-NOSSE-NEXT: movl $1431655765, %ebp # imm = 0x55555555 +; X32-NOSSE-NEXT: andl %ebp, %eax +; X32-NOSSE-NEXT: subl %eax, %esi +; X32-NOSSE-NEXT: movl %esi, %eax +; X32-NOSSE-NEXT: andl %ecx, %eax +; X32-NOSSE-NEXT: shrl $2, %esi +; X32-NOSSE-NEXT: andl %ecx, %esi +; X32-NOSSE-NEXT: addl %eax, %esi +; X32-NOSSE-NEXT: movl %esi, %eax +; X32-NOSSE-NEXT: shrl $4, %eax +; X32-NOSSE-NEXT: addl %esi, %eax +; X32-NOSSE-NEXT: movl %edx, %esi +; X32-NOSSE-NEXT: shrl %esi +; X32-NOSSE-NEXT: andl %ebp, %esi +; X32-NOSSE-NEXT: subl %esi, %edx +; X32-NOSSE-NEXT: movl %edx, %esi +; X32-NOSSE-NEXT: andl %ecx, %esi +; X32-NOSSE-NEXT: shrl $2, %edx +; X32-NOSSE-NEXT: andl %ecx, %edx +; X32-NOSSE-NEXT: addl %esi, %edx +; X32-NOSSE-NEXT: movl %edx, %ecx +; X32-NOSSE-NEXT: shrl $4, %ecx +; X32-NOSSE-NEXT: addl %edx, %ecx +; X32-NOSSE-NEXT: andl %ebx, %eax +; X32-NOSSE-NEXT: andl %ebx, %ecx +; X32-NOSSE-NEXT: imull $16843009, %eax, %eax # imm = 0x1010101 +; X32-NOSSE-NEXT: shrl $24, %eax +; X32-NOSSE-NEXT: imull $16843009, %ecx, %ecx # imm = 0x1010101 +; X32-NOSSE-NEXT: shrl $24, %ecx +; X32-NOSSE-NEXT: addl %eax, %ecx +; X32-NOSSE-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-NOSSE-NEXT: addl %edi, %ecx +; X32-NOSSE-NEXT: xorl %edx, %edx +; X32-NOSSE-NEXT: movl %edx, 12(%eax) +; X32-NOSSE-NEXT: movl %edx, 8(%eax) +; X32-NOSSE-NEXT: movl %edx, 4(%eax) +; X32-NOSSE-NEXT: movl %ecx, (%eax) +; X32-NOSSE-NEXT: popl %esi +; X32-NOSSE-NEXT: popl %edi +; X32-NOSSE-NEXT: popl %ebx +; X32-NOSSE-NEXT: popl %ebp +; X32-NOSSE-NEXT: retl $4 +; +; X64-LABEL: cnt128_pgso: +; X64: # %bb.0: +; X64-NEXT: movq %rsi, %rax +; X64-NEXT: shrq %rax +; X64-NEXT: movabsq $6148914691236517205, %r8 # imm = 0x5555555555555555 +; X64-NEXT: andq %r8, %rax +; X64-NEXT: subq %rax, %rsi +; X64-NEXT: movabsq $3689348814741910323, %rax # imm = 0x3333333333333333 +; X64-NEXT: movq %rsi, %rcx +; X64-NEXT: andq %rax, %rcx +; X64-NEXT: shrq $2, %rsi +; X64-NEXT: andq %rax, %rsi +; X64-NEXT: addq %rcx, %rsi +; X64-NEXT: movq %rsi, %rcx +; X64-NEXT: shrq $4, %rcx +; X64-NEXT: addq %rsi, %rcx +; X64-NEXT: movabsq $1085102592571150095, %r9 # imm = 0xF0F0F0F0F0F0F0F +; X64-NEXT: andq %r9, %rcx +; X64-NEXT: movabsq $72340172838076673, %rdx # imm = 0x101010101010101 +; X64-NEXT: imulq %rdx, %rcx +; X64-NEXT: shrq $56, %rcx +; X64-NEXT: movq %rdi, %rsi +; X64-NEXT: shrq %rsi +; X64-NEXT: andq %r8, %rsi +; X64-NEXT: subq %rsi, %rdi +; X64-NEXT: movq %rdi, %rsi +; X64-NEXT: andq %rax, %rsi +; X64-NEXT: shrq $2, %rdi +; X64-NEXT: andq %rax, %rdi +; X64-NEXT: addq %rsi, %rdi +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shrq $4, %rax +; X64-NEXT: addq %rdi, %rax +; X64-NEXT: andq %r9, %rax +; X64-NEXT: imulq %rdx, %rax +; X64-NEXT: shrq $56, %rax +; X64-NEXT: addq %rcx, %rax +; X64-NEXT: xorl %edx, %edx +; X64-NEXT: retq +; +; X32-POPCNT-LABEL: cnt128_pgso: +; X32-POPCNT: # %bb.0: +; X32-POPCNT-NEXT: pushl %esi +; X32-POPCNT-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx +; X32-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %edx +; X32-POPCNT-NEXT: addl %ecx, %edx +; X32-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %ecx +; X32-POPCNT-NEXT: popcntl {{[0-9]+}}(%esp), %esi +; X32-POPCNT-NEXT: addl %ecx, %esi +; X32-POPCNT-NEXT: addl %edx, %esi +; X32-POPCNT-NEXT: xorl %ecx, %ecx +; X32-POPCNT-NEXT: movl %ecx, 12(%eax) +; X32-POPCNT-NEXT: movl %ecx, 8(%eax) +; X32-POPCNT-NEXT: movl %ecx, 4(%eax) +; X32-POPCNT-NEXT: movl %esi, (%eax) +; X32-POPCNT-NEXT: popl %esi +; X32-POPCNT-NEXT: retl $4 +; +; X64-POPCNT-LABEL: cnt128_pgso: +; X64-POPCNT: # %bb.0: +; X64-POPCNT-NEXT: popcntq %rsi, %rcx +; X64-POPCNT-NEXT: popcntq %rdi, %rax +; X64-POPCNT-NEXT: addq %rcx, %rax +; X64-POPCNT-NEXT: xorl %edx, %edx +; X64-POPCNT-NEXT: retq +; +; X32-SSE2-LABEL: cnt128_pgso: +; X32-SSE2: # %bb.0: +; X32-SSE2-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-SSE2-NEXT: movq {{.*#+}} xmm0 = mem[0],zero +; X32-SSE2-NEXT: movdqa %xmm0, %xmm1 +; X32-SSE2-NEXT: psrlw $1, %xmm1 +; X32-SSE2-NEXT: movdqa {{.*#+}} xmm2 = [85,85,85,85,85,85,85,85,85,85,85,85,85,85,85,85] +; X32-SSE2-NEXT: pand %xmm2, %xmm1 +; X32-SSE2-NEXT: psubb %xmm1, %xmm0 +; X32-SSE2-NEXT: movdqa {{.*#+}} xmm1 = [51,51,51,51,51,51,51,51,51,51,51,51,51,51,51,51] +; X32-SSE2-NEXT: movdqa %xmm0, %xmm3 +; X32-SSE2-NEXT: pand %xmm1, %xmm3 +; X32-SSE2-NEXT: psrlw $2, %xmm0 +; X32-SSE2-NEXT: pand %xmm1, %xmm0 +; X32-SSE2-NEXT: paddb %xmm3, %xmm0 +; X32-SSE2-NEXT: movdqa %xmm0, %xmm3 +; X32-SSE2-NEXT: psrlw $4, %xmm3 +; X32-SSE2-NEXT: paddb %xmm0, %xmm3 +; X32-SSE2-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; X32-SSE2-NEXT: pand %xmm0, %xmm3 +; X32-SSE2-NEXT: pxor %xmm4, %xmm4 +; X32-SSE2-NEXT: psadbw %xmm4, %xmm3 +; X32-SSE2-NEXT: movd %xmm3, %ecx +; X32-SSE2-NEXT: movq {{.*#+}} xmm3 = mem[0],zero +; X32-SSE2-NEXT: movdqa %xmm3, %xmm5 +; X32-SSE2-NEXT: psrlw $1, %xmm5 +; X32-SSE2-NEXT: pand %xmm2, %xmm5 +; X32-SSE2-NEXT: psubb %xmm5, %xmm3 +; X32-SSE2-NEXT: movdqa %xmm3, %xmm2 +; X32-SSE2-NEXT: pand %xmm1, %xmm2 +; X32-SSE2-NEXT: psrlw $2, %xmm3 +; X32-SSE2-NEXT: pand %xmm1, %xmm3 +; X32-SSE2-NEXT: paddb %xmm2, %xmm3 +; X32-SSE2-NEXT: movdqa %xmm3, %xmm1 +; X32-SSE2-NEXT: psrlw $4, %xmm1 +; X32-SSE2-NEXT: paddb %xmm3, %xmm1 +; X32-SSE2-NEXT: pand %xmm0, %xmm1 +; X32-SSE2-NEXT: psadbw %xmm4, %xmm1 +; X32-SSE2-NEXT: movd %xmm1, %edx +; X32-SSE2-NEXT: addl %ecx, %edx +; X32-SSE2-NEXT: xorl %ecx, %ecx +; X32-SSE2-NEXT: movl %ecx, 12(%eax) +; X32-SSE2-NEXT: movl %ecx, 8(%eax) +; X32-SSE2-NEXT: movl %ecx, 4(%eax) +; X32-SSE2-NEXT: movl %edx, (%eax) +; X32-SSE2-NEXT: retl $4 +; +; X32-SSSE3-LABEL: cnt128_pgso: +; X32-SSSE3: # %bb.0: +; X32-SSSE3-NEXT: movl {{[0-9]+}}(%esp), %eax +; X32-SSSE3-NEXT: movdqa {{.*#+}} xmm0 = [15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15] +; X32-SSSE3-NEXT: movq {{.*#+}} xmm1 = mem[0],zero +; X32-SSSE3-NEXT: movdqa %xmm1, %xmm2 +; X32-SSSE3-NEXT: pand %xmm0, %xmm2 +; X32-SSSE3-NEXT: movdqa {{.*#+}} xmm3 = [0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4] +; X32-SSSE3-NEXT: movdqa %xmm3, %xmm4 +; X32-SSSE3-NEXT: pshufb %xmm2, %xmm4 +; X32-SSSE3-NEXT: psrlw $4, %xmm1 +; X32-SSSE3-NEXT: pand %xmm0, %xmm1 +; X32-SSSE3-NEXT: movdqa %xmm3, %xmm2 +; X32-SSSE3-NEXT: pshufb %xmm1, %xmm2 +; X32-SSSE3-NEXT: paddb %xmm4, %xmm2 +; X32-SSSE3-NEXT: pxor %xmm1, %xmm1 +; X32-SSSE3-NEXT: psadbw %xmm1, %xmm2 +; X32-SSSE3-NEXT: movd %xmm2, %ecx +; X32-SSSE3-NEXT: movq {{.*#+}} xmm2 = mem[0],zero +; X32-SSSE3-NEXT: movdqa %xmm2, %xmm4 +; X32-SSSE3-NEXT: pand %xmm0, %xmm4 +; X32-SSSE3-NEXT: movdqa %xmm3, %xmm5 +; X32-SSSE3-NEXT: pshufb %xmm4, %xmm5 +; X32-SSSE3-NEXT: psrlw $4, %xmm2 +; X32-SSSE3-NEXT: pand %xmm0, %xmm2 +; X32-SSSE3-NEXT: pshufb %xmm2, %xmm3 +; X32-SSSE3-NEXT: paddb %xmm5, %xmm3 +; X32-SSSE3-NEXT: psadbw %xmm1, %xmm3 +; X32-SSSE3-NEXT: movd %xmm3, %edx +; X32-SSSE3-NEXT: addl %ecx, %edx +; X32-SSSE3-NEXT: xorl %ecx, %ecx +; X32-SSSE3-NEXT: movl %ecx, 12(%eax) +; X32-SSSE3-NEXT: movl %ecx, 8(%eax) +; X32-SSSE3-NEXT: movl %ecx, 4(%eax) +; X32-SSSE3-NEXT: movl %edx, (%eax) +; X32-SSSE3-NEXT: retl $4 + %cnt = tail call i128 @llvm.ctpop.i128(i128 %x) + ret i128 %cnt +} + declare i8 @llvm.ctpop.i8(i8) nounwind readnone declare i16 @llvm.ctpop.i16(i16) nounwind readnone declare i32 @llvm.ctpop.i32(i32) nounwind readnone declare i64 @llvm.ctpop.i64(i64) nounwind readnone declare i128 @llvm.ctpop.i128(i128) nounwind readnone + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"ProfileSummary", !1} +!1 = !{!2, !3, !4, !5, !6, !7, !8, !9} +!2 = !{!"ProfileFormat", !"InstrProf"} +!3 = !{!"TotalCount", i64 10000} +!4 = !{!"MaxCount", i64 10} +!5 = !{!"MaxInternalCount", i64 1} +!6 = !{!"MaxFunctionCount", i64 1000} +!7 = !{!"NumCounts", i64 3} +!8 = !{!"NumFunctions", i64 3} +!9 = !{!"DetailedSummary", !10} +!10 = !{!11, !12, !13} +!11 = !{i32 10000, i64 100, i32 1} +!12 = !{i32 999000, i64 100, i32 1} +!13 = !{i32 999999, i64 1, i32 2} +!14 = !{!"function_entry_count", i64 0} diff --git a/llvm/test/CodeGen/X86/pr27202.ll b/llvm/test/CodeGen/X86/pr27202.ll index bb6be1d1685da..f3b319ead5982 100644 --- a/llvm/test/CodeGen/X86/pr27202.ll +++ b/llvm/test/CodeGen/X86/pr27202.ll @@ -14,6 +14,19 @@ define i1 @foo(i32 %i) optsize { ret i1 %cmp } +define i1 @foo_pgso(i32 %i) !prof !14 { +; CHECK-LABEL: foo_pgso: +; CHECK: # %bb.0: +; CHECK-NEXT: movl $305419896, %eax # imm = 0x12345678 +; CHECK-NEXT: andl %eax, %edi +; CHECK-NEXT: cmpl %eax, %edi +; CHECK-NEXT: sete %al +; CHECK-NEXT: retq + %and = and i32 %i, 305419896 + %cmp = icmp eq i32 %and, 305419896 + ret i1 %cmp +} + ; 8-bit ALU immediates probably have small encodings. ; We do not want to hoist the constant into a register here. @@ -52,3 +65,20 @@ define i64 @PR46237(i64 %x, i64 %y, i64 %z) optsize { %or4 = or i64 %or, %shl ret i64 %or4 } + +!llvm.module.flags = !{!0} +!0 = !{i32 1, !"ProfileSummary", !1} +!1 = !{!2, !3, !4, !5, !6, !7, !8, !9} +!2 = !{!"ProfileFormat", !"InstrProf"} +!3 = !{!"TotalCount", i64 10000} +!4 = !{!"MaxCount", i64 10} +!5 = !{!"MaxInternalCount", i64 1} +!6 = !{!"MaxFunctionCount", i64 1000} +!7 = !{!"NumCounts", i64 3} +!8 = !{!"NumFunctions", i64 3} +!9 = !{!"DetailedSummary", !10} +!10 = !{!11, !12, !13} +!11 = !{i32 10000, i64 100, i32 1} +!12 = !{i32 999000, i64 100, i32 1} +!13 = !{i32 999999, i64 1, i32 2} +!14 = !{!"function_entry_count", i64 0} From 2d3b8cc83fe85e5edcc607a0696d1e9f42ede246 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Mon, 13 Jul 2020 11:53:48 -0400 Subject: [PATCH 123/771] [libc++] Implement P0551 Make sure we satisfy the requirements added by P0551, and add tests to enforce that. --- libcxx/include/ios | 48 ++--- libcxx/include/ostream | 6 +- .../namespace/addressable_functions.sh.cpp | 185 ++++++++++++++++++ libcxx/www/cxx2a_status.html | 2 +- 4 files changed, 213 insertions(+), 28 deletions(-) create mode 100644 libcxx/test/std/namespace/addressable_functions.sh.cpp diff --git a/libcxx/include/ios b/libcxx/include/ios index d6967edbccdb7..7f0e2d65e6406 100644 --- a/libcxx/include/ios +++ b/libcxx/include/ios @@ -843,7 +843,7 @@ basic_ios<_CharT, _Traits>::set_rdbuf(basic_streambuf* _ ios_base::set_rdbuf(__sb); } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& boolalpha(ios_base& __str) { @@ -851,7 +851,7 @@ boolalpha(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& noboolalpha(ios_base& __str) { @@ -859,7 +859,7 @@ noboolalpha(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& showbase(ios_base& __str) { @@ -867,7 +867,7 @@ showbase(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& noshowbase(ios_base& __str) { @@ -875,7 +875,7 @@ noshowbase(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& showpoint(ios_base& __str) { @@ -883,7 +883,7 @@ showpoint(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& noshowpoint(ios_base& __str) { @@ -891,7 +891,7 @@ noshowpoint(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& showpos(ios_base& __str) { @@ -899,7 +899,7 @@ showpos(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& noshowpos(ios_base& __str) { @@ -907,7 +907,7 @@ noshowpos(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& skipws(ios_base& __str) { @@ -915,7 +915,7 @@ skipws(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& noskipws(ios_base& __str) { @@ -923,7 +923,7 @@ noskipws(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& uppercase(ios_base& __str) { @@ -931,7 +931,7 @@ uppercase(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& nouppercase(ios_base& __str) { @@ -939,7 +939,7 @@ nouppercase(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& unitbuf(ios_base& __str) { @@ -947,7 +947,7 @@ unitbuf(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& nounitbuf(ios_base& __str) { @@ -955,7 +955,7 @@ nounitbuf(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& internal(ios_base& __str) { @@ -963,7 +963,7 @@ internal(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& left(ios_base& __str) { @@ -971,7 +971,7 @@ left(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& right(ios_base& __str) { @@ -979,7 +979,7 @@ right(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& dec(ios_base& __str) { @@ -987,7 +987,7 @@ dec(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& hex(ios_base& __str) { @@ -995,7 +995,7 @@ hex(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& oct(ios_base& __str) { @@ -1003,7 +1003,7 @@ oct(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& fixed(ios_base& __str) { @@ -1011,7 +1011,7 @@ fixed(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& scientific(ios_base& __str) { @@ -1019,7 +1019,7 @@ scientific(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& hexfloat(ios_base& __str) { @@ -1027,7 +1027,7 @@ hexfloat(ios_base& __str) return __str; } -inline _LIBCPP_INLINE_VISIBILITY +inline ios_base& defaultfloat(ios_base& __str) { diff --git a/libcxx/include/ostream b/libcxx/include/ostream index ea3870532f329..697732d54e6d8 100644 --- a/libcxx/include/ostream +++ b/libcxx/include/ostream @@ -999,7 +999,7 @@ basic_ostream<_CharT, _Traits>::seekp(off_type __off, ios_base::seekdir __dir) } template -inline _LIBCPP_INLINE_VISIBILITY +inline basic_ostream<_CharT, _Traits>& endl(basic_ostream<_CharT, _Traits>& __os) { @@ -1009,7 +1009,7 @@ endl(basic_ostream<_CharT, _Traits>& __os) } template -inline _LIBCPP_INLINE_VISIBILITY +inline basic_ostream<_CharT, _Traits>& ends(basic_ostream<_CharT, _Traits>& __os) { @@ -1018,7 +1018,7 @@ ends(basic_ostream<_CharT, _Traits>& __os) } template -inline _LIBCPP_INLINE_VISIBILITY +inline basic_ostream<_CharT, _Traits>& flush(basic_ostream<_CharT, _Traits>& __os) { diff --git a/libcxx/test/std/namespace/addressable_functions.sh.cpp b/libcxx/test/std/namespace/addressable_functions.sh.cpp new file mode 100644 index 0000000000000..fb731abf306ca --- /dev/null +++ b/libcxx/test/std/namespace/addressable_functions.sh.cpp @@ -0,0 +1,185 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Make sure functions specified as being 'addressable' (their address can be +// taken in a well-defined manner) are indeed addressable. This notion was +// added by http://wg21.link/p0551. While it was technically only introduced +// in C++20, we test it in all standard modes because it's basic QOI to provide +// a consistent behavior for that across standard modes. + +// RUN: %{cxx} %{flags} %{compile_flags} -c %s -o %t.tu1.o -DTU1 +// RUN: %{cxx} %{flags} %{compile_flags} -c %s -o %t.tu2.o -DTU2 +// RUN: %{cxx} %{flags} %{link_flags} %t.tu1.o %t.tu2.o -o %t.exe +// RUN: %{exec} %t.exe + +#include +#include +#include +#include +#include + + +typedef std::ios_base& (FormatFlagFunction)(std::ios_base&); +typedef std::basic_ostream& (OstreamManipFunction)(std::basic_ostream&); +typedef std::basic_ostream& (WOstreamManipFunction)(std::basic_ostream&); +typedef std::basic_istream& (IstreamManipFunction)(std::basic_istream&); +typedef std::basic_istream& (WIstreamManipFunction)(std::basic_istream&); + +extern FormatFlagFunction* get_formatflag_tu1(std::string); +extern FormatFlagFunction* get_formatflag_tu2(std::string); + +extern OstreamManipFunction* get_ostreammanip_tu1(std::string); +extern OstreamManipFunction* get_ostreammanip_tu2(std::string); +extern WOstreamManipFunction* get_wostreammanip_tu1(std::string); +extern WOstreamManipFunction* get_wostreammanip_tu2(std::string); + +extern IstreamManipFunction* get_istreammanip_tu1(std::string); +extern IstreamManipFunction* get_istreammanip_tu2(std::string); +extern WIstreamManipFunction* get_wistreammanip_tu1(std::string); +extern WIstreamManipFunction* get_wistreammanip_tu2(std::string); + +#ifdef TU1 +FormatFlagFunction* get_formatflag_tu1(std::string func) +#else +FormatFlagFunction* get_formatflag_tu2(std::string func) +#endif +{ + std::map all_funcs; + + // [fmtflags.manip] + all_funcs.insert(std::make_pair("boolalpha", &std::boolalpha)); + all_funcs.insert(std::make_pair("noboolalpha", &std::noboolalpha)); + all_funcs.insert(std::make_pair("showbase", &std::showbase)); + all_funcs.insert(std::make_pair("noshowbase", &std::noshowbase)); + all_funcs.insert(std::make_pair("showpoint", &std::showpoint)); + all_funcs.insert(std::make_pair("noshowpoint", &std::noshowpoint)); + all_funcs.insert(std::make_pair("showpos", &std::showpos)); + all_funcs.insert(std::make_pair("noshowpos", &std::noshowpos)); + all_funcs.insert(std::make_pair("skipws", &std::skipws)); + all_funcs.insert(std::make_pair("noskipws", &std::noskipws)); + all_funcs.insert(std::make_pair("uppercase", &std::uppercase)); + all_funcs.insert(std::make_pair("nouppercase", &std::nouppercase)); + all_funcs.insert(std::make_pair("unitbuf", &std::unitbuf)); + all_funcs.insert(std::make_pair("nounitbuf", &std::nounitbuf)); + + // [adjustfield.manip] + all_funcs.insert(std::make_pair("internal", &std::internal)); + all_funcs.insert(std::make_pair("left", &std::left)); + all_funcs.insert(std::make_pair("right", &std::right)); + + // [basefield.manip] + all_funcs.insert(std::make_pair("dec", &std::dec)); + all_funcs.insert(std::make_pair("hex", &std::hex)); + all_funcs.insert(std::make_pair("oct", &std::oct)); + + // [floatfield.manip] + all_funcs.insert(std::make_pair("fixed", &std::fixed)); + all_funcs.insert(std::make_pair("scientific", &std::scientific)); + all_funcs.insert(std::make_pair("hexfloat", &std::hexfloat)); + all_funcs.insert(std::make_pair("defaultfloat", &std::defaultfloat)); + + return all_funcs.at(func); +} + +// [ostream.manip] (char) +#ifdef TU1 +OstreamManipFunction* get_ostreammanip_tu1(std::string func) +#else +OstreamManipFunction* get_ostreammanip_tu2(std::string func) +#endif +{ + std::map all_funcs; + typedef std::char_traits Traits; + all_funcs.insert(std::make_pair("endl", &std::endl)); + all_funcs.insert(std::make_pair("ends", &std::ends)); + all_funcs.insert(std::make_pair("flush", &std::flush)); + return all_funcs.at(func); +} + +// [ostream.manip] (wchar_t) +#ifdef TU1 +WOstreamManipFunction* get_wostreammanip_tu1(std::string func) +#else +WOstreamManipFunction* get_wostreammanip_tu2(std::string func) +#endif +{ + std::map all_funcs; + typedef std::char_traits Traits; + all_funcs.insert(std::make_pair("endl", &std::endl)); + all_funcs.insert(std::make_pair("ends", &std::ends)); + all_funcs.insert(std::make_pair("flush", &std::flush)); + return all_funcs.at(func); +} + +// [istream.manip] (char) +#ifdef TU1 +IstreamManipFunction* get_istreammanip_tu1(std::string func) +#else +IstreamManipFunction* get_istreammanip_tu2(std::string func) +#endif +{ + std::map all_funcs; + typedef std::char_traits Traits; + all_funcs.insert(std::make_pair("ws", &std::ws)); + return all_funcs.at(func); +} + +// [istream.manip] (wchar_t) +#ifdef TU1 +WIstreamManipFunction* get_wistreammanip_tu1(std::string func) +#else +WIstreamManipFunction* get_wistreammanip_tu2(std::string func) +#endif +{ + std::map all_funcs; + typedef std::char_traits Traits; + all_funcs.insert(std::make_pair("ws", &std::ws)); + return all_funcs.at(func); +} + + +#ifdef TU2 + int main() { + assert(get_formatflag_tu1("boolalpha") == get_formatflag_tu2("boolalpha")); + assert(get_formatflag_tu1("noboolalpha") == get_formatflag_tu2("noboolalpha")); + assert(get_formatflag_tu1("showbase") == get_formatflag_tu2("showbase")); + assert(get_formatflag_tu1("noshowbase") == get_formatflag_tu2("noshowbase")); + assert(get_formatflag_tu1("showpoint") == get_formatflag_tu2("showpoint")); + assert(get_formatflag_tu1("noshowpoint") == get_formatflag_tu2("noshowpoint")); + assert(get_formatflag_tu1("showpos") == get_formatflag_tu2("showpos")); + assert(get_formatflag_tu1("noshowpos") == get_formatflag_tu2("noshowpos")); + assert(get_formatflag_tu1("skipws") == get_formatflag_tu2("skipws")); + assert(get_formatflag_tu1("noskipws") == get_formatflag_tu2("noskipws")); + assert(get_formatflag_tu1("uppercase") == get_formatflag_tu2("uppercase")); + assert(get_formatflag_tu1("nouppercase") == get_formatflag_tu2("nouppercase")); + assert(get_formatflag_tu1("unitbuf") == get_formatflag_tu2("unitbuf")); + assert(get_formatflag_tu1("nounitbuf") == get_formatflag_tu2("nounitbuf")); + assert(get_formatflag_tu1("internal") == get_formatflag_tu2("internal")); + assert(get_formatflag_tu1("left") == get_formatflag_tu2("left")); + assert(get_formatflag_tu1("right") == get_formatflag_tu2("right")); + assert(get_formatflag_tu1("dec") == get_formatflag_tu2("dec")); + assert(get_formatflag_tu1("hex") == get_formatflag_tu2("hex")); + assert(get_formatflag_tu1("oct") == get_formatflag_tu2("oct")); + assert(get_formatflag_tu1("fixed") == get_formatflag_tu2("fixed")); + assert(get_formatflag_tu1("scientific") == get_formatflag_tu2("scientific")); + assert(get_formatflag_tu1("hexfloat") == get_formatflag_tu2("hexfloat")); + assert(get_formatflag_tu1("defaultfloat") == get_formatflag_tu2("defaultfloat")); + + assert(get_ostreammanip_tu1("endl") == get_ostreammanip_tu2("endl")); + assert(get_ostreammanip_tu1("ends") == get_ostreammanip_tu2("ends")); + assert(get_ostreammanip_tu1("flush") == get_ostreammanip_tu2("flush")); + + assert(get_wostreammanip_tu1("endl") == get_wostreammanip_tu2("endl")); + assert(get_wostreammanip_tu1("ends") == get_wostreammanip_tu2("ends")); + assert(get_wostreammanip_tu1("flush") == get_wostreammanip_tu2("flush")); + + assert(get_istreammanip_tu1("ws") == get_istreammanip_tu2("ws")); + + assert(get_wistreammanip_tu1("ws") == get_wistreammanip_tu2("ws")); + } +#endif diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html index 6a2f2f44d1456..ad9bb36859cb3 100644 --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -73,7 +73,7 @@

Paper Status

P0777R1LWGTreating Unnecessary decayAlbuquerqueComplete7.0 P0122R7LWG<span>JacksonvilleComplete7.0 P0355R7LWGExtending chrono to Calendars and Time ZonesJacksonvilleIn progress - P0551R3LWGThou Shalt Not Specialize std Function Templates!Jacksonville + P0551R3LWGThou Shalt Not Specialize std Function Templates!JacksonvilleComplete11.0 P0753R2LWGManipulators for C++ Synchronized Buffered OstreamJacksonville P0754R2LWG<version>JacksonvilleComplete7.0 P0809R0LWGComparing Unordered ContainersJacksonville From db091e12b2358255d249c9f3f211f4474e2c723c Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 13 Jul 2020 10:39:13 -0400 Subject: [PATCH 124/771] RISCV: Avoid GlobalISel build break in a future patch The GlobalISelEmitter is stricter about matching timm instruction outputs to timm inputs (although in an accidental sort of way that doesn't hit a proper import failure error). Also, apparently no intrinsic patterns were importing since the ID enum declaration was missing. --- llvm/lib/Target/RISCV/RISCVInstrInfoA.td | 8 ++++---- llvm/lib/Target/RISCV/RISCVInstructionSelector.cpp | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td index de73c8df93679..7fce37519b93e 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoA.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoA.td @@ -235,13 +235,13 @@ class PseudoMaskedAMOUMinUMax class PseudoMaskedAMOPat : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering), - (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, imm:$ordering)>; + (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, timm:$ordering)>; class PseudoMaskedAMOMinMaxPat : Pat<(intrin GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, timm:$ordering), (AMOInst GPR:$addr, GPR:$incr, GPR:$mask, GPR:$shiftamt, - imm:$ordering)>; + timm:$ordering)>; def PseudoMaskedAtomicSwap32 : PseudoMaskedAMO; def : PseudoMaskedAMOPat; + GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>; } // Predicates = [HasStdExtA] @@ -387,5 +387,5 @@ defm : PseudoCmpXchgPat<"atomic_cmp_swap_64", PseudoCmpXchg64>; def : Pat<(int_riscv_masked_cmpxchg_i64 GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering), (PseudoMaskedCmpXchg32 - GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, imm:$ordering)>; + GPR:$addr, GPR:$cmpval, GPR:$newval, GPR:$mask, timm:$ordering)>; } // Predicates = [HasStdExtA, IsRV64] diff --git a/llvm/lib/Target/RISCV/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/RISCVInstructionSelector.cpp index 5bd09a546114f..4d1f47da209d0 100644 --- a/llvm/lib/Target/RISCV/RISCVInstructionSelector.cpp +++ b/llvm/lib/Target/RISCV/RISCVInstructionSelector.cpp @@ -16,6 +16,7 @@ #include "RISCVTargetMachine.h" #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" +#include "llvm/IR/IntrinsicsRISCV.h" #include "llvm/Support/Debug.h" #define DEBUG_TYPE "riscv-isel" From 2e2af6026b43511f8681397a9b6f13525dda970f Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Mon, 13 Jul 2020 13:14:29 -0400 Subject: [PATCH 125/771] TableGen/GlobalISel: Emit enum names for reg class ID instead of value This was emitting the raw value for the reg class ID with a comment for the actual class name. Switch to emitting the qualified enum name instead, which obviates the need for the comment and also helps keep the lit tests on the emitter output more stable. --- llvm/test/TableGen/GlobalISelEmitter.td | 2 +- .../TableGen/GlobalISelEmitterRegSequence.td | 12 ++--- llvm/test/TableGen/GlobalISelEmitterSubreg.td | 44 +++++++++---------- llvm/utils/TableGen/GlobalISelEmitter.cpp | 4 +- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td index 6eb84925db790..5c276e7a56d3c 100644 --- a/llvm/test/TableGen/GlobalISelEmitter.td +++ b/llvm/test/TableGen/GlobalISelEmitter.td @@ -1120,7 +1120,7 @@ def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1), // NOOPT-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/1, /*RC*/MyTarget::FPR32RegClassID, // NOOPT-NEXT: // (bitconvert:{ *:[i32] } FPR32:{ *:[f32] }:$src1) => (COPY_TO_REGCLASS:{ *:[i32] } FPR32:{ *:[f32] }:$src1, GPR32:{ *:[i32] }) // NOOPT-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/TargetOpcode::COPY, -// NOOPT-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC GPR32*/1, +// NOOPT-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, MyTarget::GPR32RegClassID, // NOOPT-NEXT: // GIR_Coverage, 25, // NOOPT-NEXT: GIR_Done, // NOOPT-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]] diff --git a/llvm/test/TableGen/GlobalISelEmitterRegSequence.td b/llvm/test/TableGen/GlobalISelEmitterRegSequence.td index 6556bc3cdf29d..1b7391497f125 100644 --- a/llvm/test/TableGen/GlobalISelEmitterRegSequence.td +++ b/llvm/test/TableGen/GlobalISelEmitterRegSequence.td @@ -56,9 +56,9 @@ def SUBSOME_INSN : I<(outs SRegs:$dst), (ins SOP:$src), []>; // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/1, /*TempRegFlags*/0, // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*SubRegIndex*/2, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, /*RC SRegs*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/3, /*RC SRegs*/0, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, Test::DRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, Test::SRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/3, Test::SRegsRegClassID, def : Pat<(i32 (sext SOP:$src)), (REG_SEQUENCE DRegs, (SUBSOME_INSN SOP:$src), sub0, (SUBSOME_INSN SOP:$src), sub1)>; @@ -71,9 +71,9 @@ def : Pat<(i32 (sext SOP:$src)), // CHECK-NEXT: GIR_AddImm, /*InsnID*/1, /*SubRegIndex*/1, // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/2, /*TempRegFlags*/0, // CHECK-NEXT: GIR_AddImm, /*InsnID*/1, /*SubRegIndex*/2, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, /*RC SRegs*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/3, /*RC SRegs*/0, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, Test::DRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, Test::SRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/3, Test::SRegsRegClassID, // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::SOME_INSN, // Make sure operands are constrained when REG_SEQUENCE isn't the root instruction. def : Pat<(i32 (zext SOP:$src)), diff --git a/llvm/test/TableGen/GlobalISelEmitterSubreg.td b/llvm/test/TableGen/GlobalISelEmitterSubreg.td index aae996e8e2242..e8dc4a9ac4a07 100644 --- a/llvm/test/TableGen/GlobalISelEmitterSubreg.td +++ b/llvm/test/TableGen/GlobalISelEmitterSubreg.td @@ -57,9 +57,9 @@ def : Pat<(i32 (anyext i16:$src)), (INSERT_SUBREG (i32 (IMPLICIT_DEF)), SOP:$src // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/1, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/2, /*RC SRegs*/0, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, Test::DRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, Test::DRegsRegClassID +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/2, Test::SRegsRegClassID, // Test that we can import INSERT_SUBREG when it is a subinstruction of another @@ -76,9 +76,9 @@ def : Pat<(i32 (anyext i16:$src)), (SOME_INSN (INSERT_SUBREG (i32 (IMPLICIT_DEF) // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/1, /*TempRegFlags*/0, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/1, /*OldInsnID*/0, /*OpIdx*/1, // src // CHECK-NEXT: GIR_AddImm, /*InsnID*/1, /*Imm*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/2, /*RC SRegs*/0, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, Test::DRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, Test::DRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/2, Test::SRegsRegClassID, // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::SOME_INSN, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, @@ -92,9 +92,9 @@ def : Pat<(i32 (anyext i16:$src)), (SOME_INSN (INSERT_SUBREG (i32 (IMPLICIT_DEF) def : Pat<(i32 (anyext i16:$src)), (INSERT_SUBREG (i32 (COPY_TO_REGCLASS SOP:$src, ERegs)), SOP:$src, sub0)>; // CHECK-LABEL: (anyext:{ *:[i32] } i16:{ *:[i16] }:$src) => (INSERT_SUBREG:{ *:[i32] } (COPY_TO_REGCLASS:{ *:[i32] } SOP:{ *:[i16] }:$src, ERegs:{ *:[i32] }), SOP:{ *:[i16] }:$src, sub0:{ *:[i32] }) // CHECK: GIR_BuildMI, /*InsnID*/0, /*Opcode*/TargetOpcode::INSERT_SUBREG, -// CHECK-DAG: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC ERegs*/2, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, /*RC ERegs*/2, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/2, /*RC SRegs*/0, +// CHECK-DAG: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, Test::ERegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, Test::ERegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/2, Test::SRegsRegClassID, // Test that we can import INSERT_SUBREG when its subregister source is defined // by a subinstruction. @@ -115,9 +115,9 @@ def : Pat<(i32 (anyext i16:$src)), (INSERT_SUBREG (i32 (IMPLICIT_DEF)), (SUBSOME // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/1, /*TempRegFlags*/0, // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/1, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/2, /*RC SRegs*/0, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, Test::DRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, Test::DRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/2, Test::SRegsRegClassID, // Test an EXTRACT_SUBREG that is a sub instruction. The individual // operands should be constrained to specific register classes, and @@ -129,8 +129,8 @@ def : Pat<(i16 (trunc (not DOP:$src))), // CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/RegState::Define, // CHECK-NEXT: GIR_CopySubReg, /*NewInsnID*/1, /*OldInsnID*/1, /*OpIdx*/1, /*SubRegIdx*/1, // src -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, /*RC SRegs*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, /*RC DRegs*/1, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, Test::SRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, Test::DRegsRegClassID, // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::SUBSOME_INSN, // Test an extract from an output instruction result (nonleaf) @@ -150,8 +150,8 @@ def : Pat<(i16 (trunc (bitreverse DOP:$src))), // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_AddTempSubRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, sub0, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC SRegs*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, /*RC DRegs*/1, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, Test::SRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, Test::DRegsRegClassID, // EXTRACT_SUBREG is subinstruction, but also doesn't have a leaf input @@ -169,8 +169,8 @@ def : Pat<(i16 (trunc (bitreverse DOP:$src))), // CHECK-NEXT: GIR_BuildMI, /*InsnID*/1, /*Opcode*/TargetOpcode::COPY, // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/1, /*TempRegID*/0, /*TempRegFlags*/RegState::Define, // CHECK-NEXT: GIR_AddTempSubRegister, /*InsnID*/1, /*TempRegID*/1, /*TempRegFlags*/0, sub0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, /*RC SRegs*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, /*RC DRegs*/1, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/0, Test::SRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/1, /*Op*/1, Test::DRegsRegClassID, // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::SUBSOME_INSN2, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, @@ -187,8 +187,8 @@ def : Pat<(i16 (trunc DOP:$src)), // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_CopySubReg, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, /*SubRegIdx*/1, // src // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC SRegs*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, /*RC DRegs*/1, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, Test::SRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/1, Test::DRegsRegClassID, // Test that we can import SUBREG_TO_REG @@ -206,5 +206,5 @@ def : Pat<(i32 (zext SOP:$src)), // CHECK-NEXT: GIR_AddTempRegister, /*InsnID*/0, /*TempRegID*/0, /*TempRegFlags*/0, // CHECK-NEXT: GIR_AddImm, /*InsnID*/0, /*Imm*/1, // CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, /*RC DRegs*/1, -// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/2, /*RC SRegs*/0, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/0, Test::DRegsRegClassID, +// CHECK-NEXT: GIR_ConstrainOperandRC, /*InsnID*/0, /*Op*/2, Test::SRegsRegClassID, diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 026f9ad349444..808ab83fd9b7a 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -2960,8 +2960,8 @@ class ConstrainOperandToRegClassAction : public MatchAction { Table << MatchTable::Opcode("GIR_ConstrainOperandRC") << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID) << MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx) - << MatchTable::Comment("RC " + RC.getName()) - << MatchTable::IntValue(RC.EnumValue) << MatchTable::LineBreak; + << MatchTable::NamedValue(RC.getQualifiedName() + "RegClassID") + << MatchTable::LineBreak; } }; From acabaf600b7a28079721dd934d448aecc7c41cad Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Mon, 13 Jul 2020 10:59:55 -0700 Subject: [PATCH 126/771] [llvm][NFC] ML Policies: changed the saved_model protobuf to text Also compacted the checkpoints (variables) to one file (plus the index). This reduces the binary model files to just the variables and their index. The index is very small. The variables are serialized float arrays. When updated through training, the changes are very likely unlocalized, so there's very little value in them being anything else than binary. --- .../Analysis/models/inliner/saved_model.pb | Bin 235687 -> 0 bytes .../Analysis/models/inliner/saved_model.pbtxt | 32634 ++++++++++++++++ ...of-00002 => variables.data-00000-of-00001} | Bin 30496 -> 39110 bytes .../variables/variables.data-00000-of-00002 | Bin 7051 -> 0 bytes .../models/inliner/variables/variables.index | Bin 382 -> 377 bytes 5 files changed, 32634 insertions(+) delete mode 100644 llvm/lib/Analysis/models/inliner/saved_model.pb create mode 100644 llvm/lib/Analysis/models/inliner/saved_model.pbtxt rename llvm/lib/Analysis/models/inliner/variables/{variables.data-00001-of-00002 => variables.data-00000-of-00001} (77%) delete mode 100644 llvm/lib/Analysis/models/inliner/variables/variables.data-00000-of-00002 diff --git a/llvm/lib/Analysis/models/inliner/saved_model.pb b/llvm/lib/Analysis/models/inliner/saved_model.pb deleted file mode 100644 index 5488989454f72d8956bba4d298ef9a1ca7047b4e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 235687 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 Lu+#h-A<_Q>sDKA$ diff --git a/llvm/lib/Analysis/models/inliner/saved_model.pbtxt b/llvm/lib/Analysis/models/inliner/saved_model.pbtxt new file mode 100644 index 0000000000000..ec522a8b7c353 --- /dev/null +++ b/llvm/lib/Analysis/models/inliner/saved_model.pbtxt @@ -0,0 +1,32634 @@ +saved_model_schema_version: 1 +meta_graphs { + meta_info_def { + stripped_op_list { + op { + name: "Const" + output_arg { + name: "output" + type_attr: "dtype" + } + attr { + name: "value" + type: "tensor" + } + attr { + name: "dtype" + type: "type" + } + } + op { + name: "NoOp" + } + op { + name: "PartitionedCall" + input_arg { + name: "args" + type_list_attr: "Tin" + } + output_arg { + name: "output" + type_list_attr: "Tout" + } + attr { + name: "Tin" + type: "list(type)" + has_minimum: true + } + attr { + name: "Tout" + type: "list(type)" + has_minimum: true + } + attr { + name: "f" + type: "func" + } + attr { + name: "config" + type: "string" + default_value { + s: "" + } + } + attr { + name: "config_proto" + type: "string" + default_value { + s: "" + } + } + attr { + name: "executor_type" + type: "string" + default_value { + s: "" + } + } + } + op { + name: "Placeholder" + output_arg { + name: "output" + type_attr: "dtype" + } + attr { + name: "dtype" + type: "type" + } + attr { + name: "shape" + type: "shape" + default_value { + shape { + unknown_rank: true + } + } + } + } + op { + name: "ReadVariableOp" + input_arg { + name: "resource" + type: DT_RESOURCE + } + output_arg { + name: "value" + type_attr: "dtype" + } + attr { + name: "dtype" + type: "type" + } + is_stateful: true + } + op { + name: "StatefulPartitionedCall" + input_arg { + name: "args" + type_list_attr: "Tin" + } + output_arg { + name: "output" + type_list_attr: "Tout" + } + attr { + name: "Tin" + type: "list(type)" + has_minimum: true + } + attr { + name: "Tout" + type: "list(type)" + has_minimum: true + } + attr { + name: "f" + type: "func" + } + attr { + name: "config" + type: "string" + default_value { + s: "" + } + } + attr { + name: "config_proto" + type: "string" + default_value { + s: "" + } + } + attr { + name: "executor_type" + type: "string" + default_value { + s: "" + } + } + is_stateful: true + } + op { + name: "VarHandleOp" + output_arg { + name: "resource" + type: DT_RESOURCE + } + attr { + name: "container" + type: "string" + default_value { + s: "" + } + } + attr { + name: "shared_name" + type: "string" + default_value { + s: "" + } + } + attr { + name: "dtype" + type: "type" + } + attr { + name: "shape" + type: "shape" + } + attr { + name: "allowed_devices" + type: "list(string)" + default_value { + list { + } + } + } + is_stateful: true + } + } + tags: "serve" + tensorflow_version: "1.15.0" + tensorflow_git_version: "unknown" + stripped_default_attrs: true + } + graph_def { + node { + name: "train_step" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + } + } + } + attr { + key: "shared_name" + value { + s: "train_step" + } + } + } + node { + name: "train_step/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "train_step" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + } + node { + name: "QNetwork/EncodingNetwork/dense/kernel" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 34 + } + dim { + size: 100 + } + } + } + } + attr { + key: "shared_name" + value { + s: "QNetwork/EncodingNetwork/dense/kernel" + } + } + } + node { + name: "QNetwork/EncodingNetwork/dense/kernel/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "QNetwork/EncodingNetwork/dense/kernel" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 34 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "QNetwork/EncodingNetwork/dense/bias" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 100 + } + } + } + } + attr { + key: "shared_name" + value { + s: "QNetwork/EncodingNetwork/dense/bias" + } + } + } + node { + name: "QNetwork/EncodingNetwork/dense/bias/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "QNetwork/EncodingNetwork/dense/bias" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "QNetwork/EncodingNetwork/dense_1/kernel" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 100 + } + dim { + size: 40 + } + } + } + } + attr { + key: "shared_name" + value { + s: "QNetwork/EncodingNetwork/dense_1/kernel" + } + } + } + node { + name: "QNetwork/EncodingNetwork/dense_1/kernel/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "QNetwork/EncodingNetwork/dense_1/kernel" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 40 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "QNetwork/EncodingNetwork/dense_1/bias" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 40 + } + } + } + } + attr { + key: "shared_name" + value { + s: "QNetwork/EncodingNetwork/dense_1/bias" + } + } + } + node { + name: "QNetwork/EncodingNetwork/dense_1/bias/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "QNetwork/EncodingNetwork/dense_1/bias" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 40 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "QNetwork/dense_2/kernel" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 40 + } + dim { + size: 2 + } + } + } + } + attr { + key: "shared_name" + value { + s: "QNetwork/dense_2/kernel" + } + } + } + node { + name: "QNetwork/dense_2/kernel/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "QNetwork/dense_2/kernel" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 40 + } + dim { + size: 2 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "QNetwork/dense_2/bias" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 2 + } + } + } + } + attr { + key: "shared_name" + value { + s: "QNetwork/dense_2/bias" + } + } + } + node { + name: "QNetwork/dense_2/bias/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "QNetwork/dense_2/bias" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 2 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "NoOp" + op: "NoOp" + } + node { + name: "Const" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + } + string_val: "\nu\n\023\010\001\022\017_time_step_spec\n\024\010\002\022\020_trajectory_spec\n\023\010\003\022\017_wrapped_policy\n\016\010\004\022\ntrain_step\n\023\010\005\022\017model_variables\n\016\010\006\022\nsignatures\n\030\n\017\010\007\022\013observation\n\005\010\007\022\0013\n\030\n\017\010\007\022\013observation\n\005\010\007\022\0011\n;\n\016\010\010\022\n_q_network\n\023\010\001\022\017_time_step_spec\n\024\010\t\022\020_trajectory_spec\nE\022C\n\016VARIABLE_VALUE\022\ntrain_step\032%train_step/.ATTRIBUTES/VARIABLE_VALUE\n*\n\005\010\n\022\0010\n\005\010\013\022\0011\n\005\010\014\022\0012\n\005\010\r\022\0013\n\005\010\016\022\0014\n\005\010\017\022\0015\n\000\n\000\n\214\001\n\026\010\020\022\022_input_tensor_spec\n\014\010\021\022\010_encoder\n\022\010\022\022\016_q_value_layer\n\r\010\023\022\tvariables\n\031\010\024\022\025regularization_losses\n\027\010\025\022\023trainable_variables\n\r\010\026\022\tkeras_api\n\030\n\017\010\007\022\013observation\n\005\010\007\022\0011\ng\022e\n\016VARIABLE_VALUE\022%QNetwork/EncodingNetwork/dense/kernel\032,model_variables/0/.ATTRIBUTES/VARIABLE_VALUE\ne\022c\n\016VARIABLE_VALUE\022#QNetwork/EncodingNetwork/dense/bias\032,model_variables/1/.ATTRIBUTES/VARIABLE_VALUE\ni\022g\n\016VARIABLE_VALUE\022\'QNetwork/EncodingNetwork/dense_1/kernel\032,model_variables/2/.ATTRIBUTES/VARIABLE_VALUE\ng\022e\n\016VARIABLE_VALUE\022%QNetwork/EncodingNetwork/dense_1/bias\032,model_variables/3/.ATTRIBUTES/VARIABLE_VALUE\nY\022W\n\016VARIABLE_VALUE\022\027QNetwork/dense_2/kernel\032,model_variables/4/.ATTRIBUTES/VARIABLE_VALUE\nW\022U\n\016VARIABLE_VALUE\022\025QNetwork/dense_2/bias\032,model_variables/5/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\334\001\n\026\010\027\022\022_input_tensor_spec\n\027\010\030\022\023_preprocessing_nest\n\036\010\031\022\032_flat_preprocessing_layers\n\033\010\032\022\027_preprocessing_combiner\n\032\010\033\022\026_postprocessing_layers\n\r\010\034\022\tvariables\n\031\010\035\022\025regularization_losses\n\027\010\036\022\023trainable_variables\n\r\010\037\022\tkeras_api\nh\n\n\010\016\022\006kernel\n\010\010\017\022\004bias\n\r\010 \022\tvariables\n\031\010!\022\025regularization_losses\n\027\010\"\022\023trainable_variables\n\r\010#\022\tkeras_api\n*\n\005\010\n\022\0010\n\005\010\013\022\0011\n\005\010\014\022\0012\n\005\010\r\022\0013\n\005\010\016\022\0014\n\005\010\017\022\0015\n\000\n*\n\005\010\n\022\0010\n\005\010\013\022\0011\n\005\010\014\022\0012\n\005\010\r\022\0013\n\005\010\016\022\0014\n\005\010\017\022\0015\n\255\001\n\021\010$\022\rlayer_metrics\n\r\010\023\022\tvariables\n\037\010%\022\033layer_regularization_losses\n\013\010&\022\007metrics\n\n\010\'\022\006layers\n\031\010\024\022\025regularization_losses\n\033\010(\022\027non_trainable_variables\n\027\010\025\022\023trainable_variables\n\000\n\000\nV\n\005\010)\022\0010\n\005\010*\022\0011\n\005\010+\022\0012\n\005\010,\022\0013\n\005\010-\022\0014\n\005\010.\022\0015\n\005\010/\022\0016\n\005\0100\022\0017\n\005\0101\022\0018\n\005\0102\022\0019\n\006\0103\022\00210\n\006\0104\022\00211\nR\n\r\0105\022\tvariables\n\031\0106\022\025regularization_losses\n\027\0107\022\023trainable_variables\n\r\0108\022\tkeras_api\n\025\n\005\0109\022\0010\n\005\010:\022\0011\n\005\010;\022\0012\n\034\n\005\010\n\022\0010\n\005\010\013\022\0011\n\005\010\014\022\0012\n\005\010\r\022\0013\n\000\n\034\n\005\010\n\022\0010\n\005\010\013\022\0011\n\005\010\014\022\0012\n\005\010\r\022\0013\n\255\001\n\021\010<\022\rlayer_metrics\n\r\010\034\022\tvariables\n\037\010=\022\033layer_regularization_losses\n\013\010>\022\007metrics\n\n\010?\022\006layers\n\031\010\035\022\025regularization_losses\n\033\010@\022\027non_trainable_variables\n\027\010\036\022\023trainable_variables\n\016\n\005\010\016\022\0010\n\005\010\017\022\0011\n\000\n\016\n\005\010\016\022\0010\n\005\010\017\022\0011\n\255\001\n\021\010A\022\rlayer_metrics\n\r\010 \022\tvariables\n\037\010B\022\033layer_regularization_losses\n\013\010C\022\007metrics\n\n\010D\022\006layers\n\031\010!\022\025regularization_losses\n\033\010E\022\027non_trainable_variables\n\027\010\"\022\023trainable_variables\n\000\n\000\n\000\n\016\n\005\010\021\022\0010\n\005\010\022\022\0011\n\000\nR\n\r\010F\022\tvariables\n\031\010G\022\025regularization_losses\n\027\010H\022\023trainable_variables\n\r\010I\022\tkeras_api\nR\n\r\010J\022\tvariables\n\031\010K\022\025regularization_losses\n\027\010L\022\023trainable_variables\n\r\010M\022\tkeras_api\nR\n\r\010N\022\tvariables\n\031\010O\022\025regularization_losses\n\027\010P\022\023trainable_variables\n\r\010Q\022\tkeras_api\nR\n\r\010R\022\tvariables\n\031\010S\022\025regularization_losses\n\027\010T\022\023trainable_variables\n\r\010U\022\tkeras_api\nR\n\r\010V\022\tvariables\n\031\010W\022\025regularization_losses\n\027\010X\022\023trainable_variables\n\r\010Y\022\tkeras_api\nR\n\r\010Z\022\tvariables\n\031\010[\022\025regularization_losses\n\027\010\\\022\023trainable_variables\n\r\010]\022\tkeras_api\nR\n\r\010^\022\tvariables\n\031\010_\022\025regularization_losses\n\027\010`\022\023trainable_variables\n\r\010a\022\tkeras_api\nR\n\r\010b\022\tvariables\n\031\010c\022\025regularization_losses\n\027\010d\022\023trainable_variables\n\r\010e\022\tkeras_api\nR\n\r\010f\022\tvariables\n\031\010g\022\025regularization_losses\n\027\010h\022\023trainable_variables\n\r\010i\022\tkeras_api\nR\n\r\010j\022\tvariables\n\031\010k\022\025regularization_losses\n\027\010l\022\023trainable_variables\n\r\010m\022\tkeras_api\nR\n\r\010n\022\tvariables\n\031\010o\022\025regularization_losses\n\027\010p\022\023trainable_variables\n\r\010q\022\tkeras_api\nR\n\r\010r\022\tvariables\n\031\010s\022\025regularization_losses\n\027\010t\022\023trainable_variables\n\r\010u\022\tkeras_api\n\000\n\000\n\000\n\255\001\n\021\010v\022\rlayer_metrics\n\r\0105\022\tvariables\n\037\010w\022\033layer_regularization_losses\n\013\010x\022\007metrics\n\n\010y\022\006layers\n\031\0106\022\025regularization_losses\n\033\010z\022\027non_trainable_variables\n\027\0107\022\023trainable_variables\nR\n\r\010{\022\tvariables\n\031\010|\022\025regularization_losses\n\027\010}\022\023trainable_variables\n\r\010~\022\tkeras_api\nk\n\n\010\n\022\006kernel\n\010\010\013\022\004bias\n\r\010\177\022\tvariables\n\032\010\200\001\022\025regularization_losses\n\030\010\201\001\022\023trainable_variables\n\016\010\202\001\022\tkeras_api\nl\n\n\010\014\022\006kernel\n\010\010\r\022\004bias\n\016\010\203\001\022\tvariables\n\032\010\204\001\022\025regularization_losses\n\030\010\205\001\022\023trainable_variables\n\016\010\206\001\022\tkeras_api\n\000\n\000\n\000\nv\n\005\010)\022\0010\n\005\010*\022\0011\n\005\010+\022\0012\n\005\010,\022\0013\n\005\010-\022\0014\n\005\010.\022\0015\n\005\010/\022\0016\n\005\0100\022\0017\n\005\0101\022\0018\n\005\0102\022\0019\n\006\0103\022\00210\n\006\0104\022\00211\n\006\010\032\022\00212\n\006\0109\022\00213\n\006\010:\022\00214\n\006\010;\022\00215\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\262\001\n\022\010\207\001\022\rlayer_metrics\n\r\010F\022\tvariables\n \010\210\001\022\033layer_regularization_losses\n\014\010\211\001\022\007metrics\n\013\010\212\001\022\006layers\n\031\010G\022\025regularization_losses\n\034\010\213\001\022\027non_trainable_variables\n\027\010H\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\214\001\022\rlayer_metrics\n\r\010J\022\tvariables\n \010\215\001\022\033layer_regularization_losses\n\014\010\216\001\022\007metrics\n\013\010\217\001\022\006layers\n\031\010K\022\025regularization_losses\n\034\010\220\001\022\027non_trainable_variables\n\027\010L\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\221\001\022\rlayer_metrics\n\r\010N\022\tvariables\n \010\222\001\022\033layer_regularization_losses\n\014\010\223\001\022\007metrics\n\013\010\224\001\022\006layers\n\031\010O\022\025regularization_losses\n\034\010\225\001\022\027non_trainable_variables\n\027\010P\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\226\001\022\rlayer_metrics\n\r\010R\022\tvariables\n \010\227\001\022\033layer_regularization_losses\n\014\010\230\001\022\007metrics\n\013\010\231\001\022\006layers\n\031\010S\022\025regularization_losses\n\034\010\232\001\022\027non_trainable_variables\n\027\010T\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\233\001\022\rlayer_metrics\n\r\010V\022\tvariables\n \010\234\001\022\033layer_regularization_losses\n\014\010\235\001\022\007metrics\n\013\010\236\001\022\006layers\n\031\010W\022\025regularization_losses\n\034\010\237\001\022\027non_trainable_variables\n\027\010X\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\240\001\022\rlayer_metrics\n\r\010Z\022\tvariables\n \010\241\001\022\033layer_regularization_losses\n\014\010\242\001\022\007metrics\n\013\010\243\001\022\006layers\n\031\010[\022\025regularization_losses\n\034\010\244\001\022\027non_trainable_variables\n\027\010\\\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\245\001\022\rlayer_metrics\n\r\010^\022\tvariables\n \010\246\001\022\033layer_regularization_losses\n\014\010\247\001\022\007metrics\n\013\010\250\001\022\006layers\n\031\010_\022\025regularization_losses\n\034\010\251\001\022\027non_trainable_variables\n\027\010`\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\252\001\022\rlayer_metrics\n\r\010b\022\tvariables\n \010\253\001\022\033layer_regularization_losses\n\014\010\254\001\022\007metrics\n\013\010\255\001\022\006layers\n\031\010c\022\025regularization_losses\n\034\010\256\001\022\027non_trainable_variables\n\027\010d\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\257\001\022\rlayer_metrics\n\r\010f\022\tvariables\n \010\260\001\022\033layer_regularization_losses\n\014\010\261\001\022\007metrics\n\013\010\262\001\022\006layers\n\031\010g\022\025regularization_losses\n\034\010\263\001\022\027non_trainable_variables\n\027\010h\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\264\001\022\rlayer_metrics\n\r\010j\022\tvariables\n \010\265\001\022\033layer_regularization_losses\n\014\010\266\001\022\007metrics\n\013\010\267\001\022\006layers\n\031\010k\022\025regularization_losses\n\034\010\270\001\022\027non_trainable_variables\n\027\010l\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\271\001\022\rlayer_metrics\n\r\010n\022\tvariables\n \010\272\001\022\033layer_regularization_losses\n\014\010\273\001\022\007metrics\n\013\010\274\001\022\006layers\n\031\010o\022\025regularization_losses\n\034\010\275\001\022\027non_trainable_variables\n\027\010p\022\023trainable_variables\n\000\n\000\n\000\n\262\001\n\022\010\276\001\022\rlayer_metrics\n\r\010r\022\tvariables\n \010\277\001\022\033layer_regularization_losses\n\014\010\300\001\022\007metrics\n\013\010\301\001\022\006layers\n\031\010s\022\025regularization_losses\n\034\010\302\001\022\027non_trainable_variables\n\027\010t\022\023trainable_variables\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\262\001\n\022\010\303\001\022\rlayer_metrics\n\r\010{\022\tvariables\n \010\304\001\022\033layer_regularization_losses\n\014\010\305\001\022\007metrics\n\013\010\306\001\022\006layers\n\031\010|\022\025regularization_losses\n\034\010\307\001\022\027non_trainable_variables\n\027\010}\022\023trainable_variables\n\016\n\005\010\n\022\0010\n\005\010\013\022\0011\n\000\n\016\n\005\010\n\022\0010\n\005\010\013\022\0011\n\264\001\n\022\010\310\001\022\rlayer_metrics\n\r\010\177\022\tvariables\n \010\311\001\022\033layer_regularization_losses\n\014\010\312\001\022\007metrics\n\013\010\313\001\022\006layers\n\032\010\200\001\022\025regularization_losses\n\034\010\314\001\022\027non_trainable_variables\n\030\010\201\001\022\023trainable_variables\n\016\n\005\010\014\022\0010\n\005\010\r\022\0011\n\000\n\016\n\005\010\014\022\0010\n\005\010\r\022\0011\n\265\001\n\022\010\315\001\022\rlayer_metrics\n\016\010\203\001\022\tvariables\n \010\316\001\022\033layer_regularization_losses\n\014\010\317\001\022\007metrics\n\013\010\320\001\022\006layers\n\032\010\204\001\022\025regularization_losses\n\034\010\321\001\022\027non_trainable_variables\n\030\010\205\001\022\023trainable_variables\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000" + } + } + } + } + node { + name: "action_callee_basic_block_count" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_callee_conditionally_executed_blocks" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_callee_users" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_caller_basic_block_count" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_caller_conditionally_executed_blocks" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_caller_users" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_callsite_height" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_cost_estimate" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_discount" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_edge_count" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_inlining_default" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_node_count" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_nr_ctant_params" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_reward" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "action_step_type" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + } + node { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "action_callee_basic_block_count" + input: "action_callee_conditionally_executed_blocks" + input: "action_callee_users" + input: "action_caller_basic_block_count" + input: "action_caller_conditionally_executed_blocks" + input: "action_caller_users" + input: "action_callsite_height" + input: "action_cost_estimate" + input: "action_discount" + input: "action_edge_count" + input: "action_inlining_default" + input: "action_node_count" + input: "action_nr_ctant_params" + input: "action_reward" + input: "action_step_type" + input: "QNetwork/EncodingNetwork/dense/kernel" + input: "QNetwork/EncodingNetwork/dense/bias" + input: "QNetwork/EncodingNetwork/dense_1/kernel" + input: "QNetwork/EncodingNetwork/dense_1/bias" + input: "QNetwork/dense_2/kernel" + input: "QNetwork/dense_2/bias" + attr { + key: "Tin" + value { + list { + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_FLOAT + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_FLOAT + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 15 + i: 16 + i: 17 + i: 18 + i: 19 + i: 20 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_signature_wrapper_4619026" + } + } + } + } + node { + name: "PartitionedCall" + op: "PartitionedCall" + attr { + key: "Tin" + value { + list { + } + } + } + attr { + key: "Tout" + value { + list { + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_signature_wrapper_4619033" + } + } + } + } + node { + name: "StatefulPartitionedCall_1" + op: "StatefulPartitionedCall" + input: "train_step" + attr { + key: "Tin" + value { + list { + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 0 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_signature_wrapper_4619048" + } + } + } + } + node { + name: "saver_filename" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "shape" + value { + shape { + } + } + } + } + node { + name: "StatefulPartitionedCall_2" + op: "StatefulPartitionedCall" + input: "saver_filename" + input: "train_step/Read/ReadVariableOp" + input: "QNetwork/EncodingNetwork/dense/kernel/Read/ReadVariableOp" + input: "QNetwork/EncodingNetwork/dense/bias/Read/ReadVariableOp" + input: "QNetwork/EncodingNetwork/dense_1/kernel/Read/ReadVariableOp" + input: "QNetwork/EncodingNetwork/dense_1/bias/Read/ReadVariableOp" + input: "QNetwork/dense_2/kernel/Read/ReadVariableOp" + input: "QNetwork/dense_2/bias/Read/ReadVariableOp" + input: "Const" + attr { + key: "Tin" + value { + list { + type: DT_STRING + type: DT_INT64 + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_STRING + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_STRING + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference__traced_save_4619143" + } + } + } + } + node { + name: "StatefulPartitionedCall_3" + op: "StatefulPartitionedCall" + input: "saver_filename" + input: "train_step" + input: "QNetwork/EncodingNetwork/dense/kernel" + input: "QNetwork/EncodingNetwork/dense/bias" + input: "QNetwork/EncodingNetwork/dense_1/kernel" + input: "QNetwork/EncodingNetwork/dense_1/bias" + input: "QNetwork/dense_2/kernel" + input: "QNetwork/dense_2/bias" + attr { + key: "Tin" + value { + list { + type: DT_STRING + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_STRING + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference__traced_restore_4619176" + } + } + } + } + library { + function { + signature { + name: "__inference_signature_wrapper_4619048" + input_arg { + name: "unknown" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "unknown" + attr { + key: "Tin" + value { + list { + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 0 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_function_with_signature_4619040" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_function_with_signature_4619029" + } + node_def { + name: "PartitionedCall" + op: "PartitionedCall" + attr { + key: "Tin" + value { + list { + } + } + } + attr { + key: "Tout" + value { + list { + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_function_722" + } + } + } + experimental_debug_info { + original_node_names: "PartitionedCall" + } + } + attr { + key: "_input_shapes" + value { + } + } + } + function { + signature { + name: "__inference_action_931" + input_arg { + name: "time_step" + type: DT_INT32 + } + input_arg { + name: "time_step_1" + type: DT_FLOAT + } + input_arg { + name: "time_step_2" + type: DT_FLOAT + } + input_arg { + name: "time_step_3" + type: DT_INT64 + } + input_arg { + name: "time_step_4" + type: DT_INT64 + } + input_arg { + name: "time_step_5" + type: DT_INT64 + } + input_arg { + name: "time_step_6" + type: DT_INT64 + } + input_arg { + name: "time_step_7" + type: DT_INT64 + } + input_arg { + name: "time_step_8" + type: DT_INT64 + } + input_arg { + name: "time_step_9" + type: DT_INT64 + } + input_arg { + name: "time_step_10" + type: DT_INT64 + } + input_arg { + name: "time_step_11" + type: DT_INT64 + } + input_arg { + name: "time_step_12" + type: DT_INT64 + } + input_arg { + name: "time_step_13" + type: DT_INT64 + } + input_arg { + name: "time_step_14" + type: DT_INT64 + } + input_arg { + name: "qnetwork_encodingnetwork_dense_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "qnetwork_encodingnetwork_dense_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "qnetwork_encodingnetwork_dense_1_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "qnetwork_encodingnetwork_dense_1_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "qnetwork_dense_2_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "qnetwork_dense_2_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_3" + input: "QNetwork/EncodingNetwork/lambda/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 9 + f: 9 + f: 9 + f: 9 + f: 10 + f: 10 + f: 11 + f: 12 + f: 13 + f: 14 + f: 14 + f: 14 + f: 16 + f: 17 + f: 19 + f: 23 + f: 27 + f: 39 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_4" + input: "QNetwork/EncodingNetwork/lambda_1/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_1/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 3 + f: 3 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 7 + f: 8 + f: 8 + f: 8 + f: 8 + f: 9 + f: 10 + f: 10 + f: 10 + f: 12 + f: 12 + f: 12 + f: 14 + f: 14 + f: 18 + f: 20 + f: 23 + f: 30 + f: 41 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_1/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_1/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_1/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_1/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_1/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_1/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_1/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_1/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_1/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_1/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_1/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_1/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_5" + input: "QNetwork/EncodingNetwork/lambda_2/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_2/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 22 + f: 22 + f: 22 + f: 22 + f: 23 + f: 23 + f: 23 + f: 24 + f: 24 + f: 24 + f: 25 + f: 25 + f: 25 + f: 25 + f: 25 + f: 25 + f: 26 + f: 26 + f: 26 + f: 27 + f: 27 + f: 27 + f: 27 + f: 28 + f: 28 + f: 29 + f: 29 + f: 29 + f: 29 + f: 30 + f: 30 + f: 31 + f: 31 + f: 31 + f: 31 + f: 32 + f: 32 + f: 33 + f: 33 + f: 33 + f: 34 + f: 34 + f: 34 + f: 34 + f: 35 + f: 35 + f: 36 + f: 36 + f: 37 + f: 37 + f: 37 + f: 38 + f: 38 + f: 39 + f: 39 + f: 40 + f: 40 + f: 41 + f: 41 + f: 41 + f: 42 + f: 43 + f: 43 + f: 44 + f: 44 + f: 45 + f: 45 + f: 46 + f: 46 + f: 46 + f: 47 + f: 47 + f: 48 + f: 49 + f: 49 + f: 50 + f: 50 + f: 51 + f: 52 + f: 53 + f: 53 + f: 54 + f: 55 + f: 56 + f: 57 + f: 57 + f: 58 + f: 59 + f: 60 + f: 61 + f: 61 + f: 63 + f: 63 + f: 64 + f: 65 + f: 66 + f: 67 + f: 67 + f: 69 + f: 70 + f: 71 + f: 72 + f: 73 + f: 74 + f: 75 + f: 77 + f: 78 + f: 79 + f: 80 + f: 81 + f: 82 + f: 83 + f: 85 + f: 86 + f: 88 + f: 89 + f: 91 + f: 92 + f: 94 + f: 96 + f: 97 + f: 99 + f: 100 + f: 101 + f: 103 + f: 105 + f: 107 + f: 109 + f: 111 + f: 113 + f: 115 + f: 118 + f: 121 + f: 123 + f: 126 + f: 128 + f: 130 + f: 133 + f: 135 + f: 137 + f: 140 + f: 143 + f: 146 + f: 148 + f: 151 + f: 154 + f: 157 + f: 161 + f: 163 + f: 166 + f: 169 + f: 173 + f: 178 + f: 183 + f: 189 + f: 193 + f: 197 + f: 202 + f: 208 + f: 213 + f: 218 + f: 223 + f: 228 + f: 233 + f: 239 + f: 245 + f: 250 + f: 257 + f: 262 + f: 269 + f: 277 + f: 284 + f: 292 + f: 300 + f: 308 + f: 319 + f: 329 + f: 340 + f: 349 + f: 359 + f: 371 + f: 382 + f: 394 + f: 410 + f: 423 + f: 435 + f: 445 + f: 462 + f: 480 + f: 492 + f: 506 + f: 519 + f: 536 + f: 557 + f: 577 + f: 598 + f: 622 + f: 655 + f: 679 + f: 707 + f: 733 + f: 751 + f: 787 + f: 814 + f: 847 + f: 897 + f: 934 + f: 997 + f: 1062 + f: 1111 + f: 1181 + f: 1275 + f: 1385 + f: 1465 + f: 1603 + f: 1769 + f: 2057 + f: 2257 + f: 2803 + f: 3468 + f: 4417 + f: 6538 + f: 16126 + f: 23446 + f: 33536 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_2/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_2/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_2/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_2/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_2/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_2/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_2/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_2/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_2/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_2/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_2/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_2/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_6" + input: "QNetwork/EncodingNetwork/lambda_3/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_3/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 23 + f: 23 + f: 23 + f: 24 + f: 24 + f: 24 + f: 24 + f: 24 + f: 24 + f: 25 + f: 25 + f: 25 + f: 25 + f: 25 + f: 26 + f: 26 + f: 26 + f: 26 + f: 27 + f: 27 + f: 27 + f: 27 + f: 27 + f: 28 + f: 28 + f: 28 + f: 29 + f: 29 + f: 29 + f: 29 + f: 30 + f: 30 + f: 30 + f: 31 + f: 31 + f: 31 + f: 32 + f: 32 + f: 32 + f: 33 + f: 33 + f: 33 + f: 34 + f: 34 + f: 34 + f: 34 + f: 35 + f: 35 + f: 35 + f: 36 + f: 36 + f: 36 + f: 37 + f: 37 + f: 37 + f: 38 + f: 38 + f: 38 + f: 38 + f: 39 + f: 39 + f: 40 + f: 40 + f: 41 + f: 41 + f: 42 + f: 43 + f: 43 + f: 44 + f: 45 + f: 45 + f: 46 + f: 47 + f: 47 + f: 48 + f: 49 + f: 49 + f: 50 + f: 50 + f: 52 + f: 52 + f: 53 + f: 54 + f: 55 + f: 55 + f: 57 + f: 58 + f: 59 + f: 60 + f: 62 + f: 64 + f: 65 + f: 66 + f: 68 + f: 70 + f: 70 + f: 70 + f: 70 + f: 70 + f: 71 + f: 73 + f: 75 + f: 76 + f: 78 + f: 81 + f: 84 + f: 86 + f: 90 + f: 94 + f: 98 + f: 101 + f: 106 + f: 111 + f: 117 + f: 123 + f: 130 + f: 138 + f: 146 + f: 157 + f: 163 + f: 176 + f: 187 + f: 198 + f: 214 + f: 227 + f: 252 + f: 280 + f: 327 + f: 395 + f: 506 + f: 671 + f: 1025 + f: 1971 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_3/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_3/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_3/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_3/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_3/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_3/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_3/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_3/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_3/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_3/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_3/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_3/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_7" + input: "QNetwork/EncodingNetwork/lambda_4/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_4/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 5 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 7 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 11 + f: 11 + f: 11 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 13 + f: 13 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 19 + f: 19 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 21 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 24 + f: 24 + f: 24 + f: 24 + f: 24 + f: 24 + f: 24 + f: 24 + f: 25 + f: 26 + f: 26 + f: 26 + f: 26 + f: 26 + f: 26 + f: 26 + f: 26 + f: 26 + f: 26 + f: 27 + f: 28 + f: 28 + f: 28 + f: 28 + f: 28 + f: 29 + f: 30 + f: 30 + f: 30 + f: 30 + f: 30 + f: 30 + f: 31 + f: 32 + f: 32 + f: 32 + f: 32 + f: 32 + f: 34 + f: 34 + f: 34 + f: 34 + f: 34 + f: 34 + f: 35 + f: 36 + f: 36 + f: 36 + f: 37 + f: 38 + f: 38 + f: 38 + f: 39 + f: 40 + f: 40 + f: 41 + f: 42 + f: 42 + f: 43 + f: 44 + f: 44 + f: 46 + f: 46 + f: 47 + f: 48 + f: 48 + f: 50 + f: 50 + f: 52 + f: 52 + f: 54 + f: 55 + f: 55 + f: 56 + f: 57 + f: 58 + f: 60 + f: 60 + f: 60 + f: 60 + f: 60 + f: 60 + f: 62 + f: 62 + f: 64 + f: 65 + f: 66 + f: 68 + f: 70 + f: 72 + f: 74 + f: 77 + f: 80 + f: 82 + f: 86 + f: 89 + f: 92 + f: 96 + f: 99 + f: 104 + f: 108 + f: 114 + f: 119 + f: 125 + f: 131 + f: 139 + f: 146 + f: 157 + f: 167 + f: 176 + f: 188 + f: 198 + f: 215 + f: 236 + f: 262 + f: 306 + f: 376 + f: 462 + f: 596 + f: 942 + f: 1428 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_4/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_4/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_4/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_4/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_4/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_4/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_4/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_4/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_4/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_4/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_4/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_4/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_8" + input: "QNetwork/EncodingNetwork/lambda_5/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_5/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 10 + f: 10 + f: 11 + f: 11 + f: 12 + f: 13 + f: 14 + f: 15 + f: 16 + f: 18 + f: 20 + f: 23 + f: 29 + f: 38 + f: 60 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_5/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_5/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_5/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_5/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_5/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_5/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_5/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_5/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_5/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_5/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_5/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_5/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_9" + input: "QNetwork/EncodingNetwork/lambda_6/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_6/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 3 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 4 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 6 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 7 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 8 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 9 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 11 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 12 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 13 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 14 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 16 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 17 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 18 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 19 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 21 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 22 + f: 23 + f: 23 + f: 23 + f: 23 + f: 23 + f: 23 + f: 23 + f: 24 + f: 24 + f: 24 + f: 24 + f: 24 + f: 25 + f: 25 + f: 25 + f: 25 + f: 25 + f: 26 + f: 26 + f: 26 + f: 26 + f: 27 + f: 27 + f: 27 + f: 28 + f: 28 + f: 28 + f: 29 + f: 29 + f: 30 + f: 30 + f: 30 + f: 31 + f: 31 + f: 32 + f: 32 + f: 33 + f: 33 + f: 34 + f: 35 + f: 37 + f: 38 + f: 40 + f: 46 + f: 51 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_6/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_6/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_6/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_6/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_6/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_6/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_6/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_6/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_6/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_6/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_6/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_6/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_10" + input: "QNetwork/EncodingNetwork/lambda_7/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_7/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: -15035 + f: -15030 + f: -15025 + f: -15000 + f: -14985 + f: -14945 + f: -14745 + f: -70 + f: -55 + f: -55 + f: -50 + f: -50 + f: -50 + f: -45 + f: -45 + f: -45 + f: -45 + f: -45 + f: -45 + f: -45 + f: -45 + f: -45 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -40 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -35 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -30 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -25 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -20 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -15 + f: -10 + f: -10 + f: -10 + f: -10 + f: -10 + f: -10 + f: -10 + f: -10 + f: -10 + f: -10 + f: -10 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: -5 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 5 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 10 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 15 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 20 + f: 25 + f: 25 + f: 25 + f: 25 + f: 25 + f: 25 + f: 25 + f: 30 + f: 30 + f: 30 + f: 30 + f: 30 + f: 30 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 35 + f: 40 + f: 40 + f: 40 + f: 40 + f: 40 + f: 40 + f: 40 + f: 40 + f: 40 + f: 40 + f: 40 + f: 40 + f: 45 + f: 45 + f: 45 + f: 45 + f: 45 + f: 45 + f: 45 + f: 45 + f: 45 + f: 45 + f: 50 + f: 50 + f: 50 + f: 50 + f: 50 + f: 50 + f: 50 + f: 50 + f: 50 + f: 55 + f: 55 + f: 60 + f: 60 + f: 60 + f: 60 + f: 60 + f: 60 + f: 60 + f: 60 + f: 60 + f: 60 + f: 65 + f: 65 + f: 65 + f: 65 + f: 65 + f: 65 + f: 65 + f: 65 + f: 65 + f: 65 + f: 65 + f: 65 + f: 70 + f: 70 + f: 70 + f: 70 + f: 70 + f: 70 + f: 70 + f: 75 + f: 75 + f: 80 + f: 80 + f: 80 + f: 85 + f: 85 + f: 85 + f: 90 + f: 90 + f: 90 + f: 90 + f: 95 + f: 95 + f: 100 + f: 100 + f: 105 + f: 110 + f: 115 + f: 120 + f: 125 + f: 125 + f: 130 + f: 140 + f: 140 + f: 145 + f: 150 + f: 155 + f: 160 + f: 160 + f: 165 + f: 170 + f: 175 + f: 180 + f: 190 + f: 200 + f: 210 + f: 215 + f: 220 + f: 220 + f: 230 + f: 235 + f: 245 + f: 250 + f: 260 + f: 275 + f: 290 + f: 305 + f: 325 + f: 350 + f: 370 + f: 390 + f: 425 + f: 460 + f: 500 + f: 560 + f: 650 + f: 790 + f: 1025 + f: 1600 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_7/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_7/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_7/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_7/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_7/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_7/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_7/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_7/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_7/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_7/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_7/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_7/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_11" + input: "QNetwork/EncodingNetwork/lambda_8/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_8/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 18 + f: 29 + f: 39 + f: 48 + f: 57 + f: 64 + f: 70 + f: 76 + f: 82 + f: 87 + f: 92 + f: 97 + f: 101 + f: 105 + f: 109 + f: 113 + f: 116 + f: 120 + f: 123 + f: 127 + f: 130 + f: 134 + f: 137 + f: 140 + f: 143 + f: 146 + f: 149 + f: 152 + f: 156 + f: 159 + f: 162 + f: 165 + f: 168 + f: 171 + f: 174 + f: 177 + f: 180 + f: 183 + f: 186 + f: 188 + f: 191 + f: 194 + f: 197 + f: 200 + f: 203 + f: 205 + f: 208 + f: 211 + f: 214 + f: 217 + f: 219 + f: 222 + f: 225 + f: 228 + f: 231 + f: 233 + f: 236 + f: 239 + f: 242 + f: 244 + f: 247 + f: 250 + f: 253 + f: 255 + f: 258 + f: 261 + f: 264 + f: 266 + f: 269 + f: 272 + f: 275 + f: 278 + f: 280 + f: 283 + f: 286 + f: 289 + f: 292 + f: 294 + f: 297 + f: 300 + f: 303 + f: 305 + f: 308 + f: 311 + f: 314 + f: 317 + f: 319 + f: 322 + f: 325 + f: 327 + f: 330 + f: 333 + f: 336 + f: 339 + f: 341 + f: 344 + f: 347 + f: 350 + f: 353 + f: 355 + f: 358 + f: 361 + f: 364 + f: 367 + f: 370 + f: 373 + f: 375 + f: 378 + f: 381 + f: 384 + f: 387 + f: 390 + f: 393 + f: 396 + f: 399 + f: 401 + f: 404 + f: 407 + f: 410 + f: 413 + f: 416 + f: 419 + f: 422 + f: 425 + f: 428 + f: 431 + f: 434 + f: 437 + f: 440 + f: 443 + f: 446 + f: 449 + f: 452 + f: 455 + f: 458 + f: 461 + f: 464 + f: 467 + f: 470 + f: 473 + f: 476 + f: 479 + f: 483 + f: 486 + f: 489 + f: 492 + f: 495 + f: 498 + f: 501 + f: 504 + f: 507 + f: 511 + f: 514 + f: 517 + f: 520 + f: 523 + f: 526 + f: 530 + f: 533 + f: 536 + f: 539 + f: 542 + f: 545 + f: 549 + f: 552 + f: 555 + f: 558 + f: 562 + f: 565 + f: 569 + f: 572 + f: 575 + f: 579 + f: 582 + f: 585 + f: 589 + f: 592 + f: 595 + f: 599 + f: 602 + f: 605 + f: 609 + f: 612 + f: 616 + f: 620 + f: 623 + f: 626 + f: 630 + f: 634 + f: 637 + f: 641 + f: 644 + f: 648 + f: 651 + f: 655 + f: 658 + f: 662 + f: 665 + f: 669 + f: 672 + f: 676 + f: 680 + f: 683 + f: 687 + f: 691 + f: 694 + f: 698 + f: 702 + f: 705 + f: 709 + f: 712 + f: 716 + f: 720 + f: 724 + f: 727 + f: 731 + f: 735 + f: 739 + f: 742 + f: 746 + f: 750 + f: 754 + f: 758 + f: 761 + f: 765 + f: 769 + f: 773 + f: 777 + f: 780 + f: 784 + f: 788 + f: 792 + f: 796 + f: 800 + f: 804 + f: 808 + f: 812 + f: 816 + f: 820 + f: 823 + f: 828 + f: 832 + f: 836 + f: 840 + f: 844 + f: 848 + f: 852 + f: 856 + f: 860 + f: 864 + f: 868 + f: 873 + f: 877 + f: 881 + f: 885 + f: 889 + f: 893 + f: 897 + f: 902 + f: 906 + f: 910 + f: 914 + f: 919 + f: 923 + f: 927 + f: 931 + f: 935 + f: 940 + f: 944 + f: 948 + f: 953 + f: 957 + f: 962 + f: 966 + f: 970 + f: 975 + f: 979 + f: 984 + f: 988 + f: 993 + f: 997 + f: 1002 + f: 1006 + f: 1011 + f: 1015 + f: 1020 + f: 1024 + f: 1029 + f: 1034 + f: 1038 + f: 1043 + f: 1047 + f: 1052 + f: 1057 + f: 1062 + f: 1066 + f: 1071 + f: 1076 + f: 1081 + f: 1086 + f: 1090 + f: 1095 + f: 1100 + f: 1105 + f: 1110 + f: 1114 + f: 1119 + f: 1124 + f: 1129 + f: 1134 + f: 1139 + f: 1144 + f: 1149 + f: 1154 + f: 1159 + f: 1164 + f: 1169 + f: 1174 + f: 1179 + f: 1184 + f: 1189 + f: 1194 + f: 1199 + f: 1204 + f: 1209 + f: 1215 + f: 1220 + f: 1225 + f: 1230 + f: 1235 + f: 1241 + f: 1246 + f: 1251 + f: 1257 + f: 1262 + f: 1267 + f: 1273 + f: 1278 + f: 1284 + f: 1289 + f: 1294 + f: 1300 + f: 1305 + f: 1311 + f: 1316 + f: 1322 + f: 1327 + f: 1333 + f: 1338 + f: 1344 + f: 1350 + f: 1355 + f: 1361 + f: 1367 + f: 1372 + f: 1378 + f: 1383 + f: 1389 + f: 1395 + f: 1401 + f: 1407 + f: 1413 + f: 1418 + f: 1424 + f: 1430 + f: 1436 + f: 1442 + f: 1448 + f: 1454 + f: 1459 + f: 1465 + f: 1472 + f: 1477 + f: 1483 + f: 1489 + f: 1495 + f: 1501 + f: 1507 + f: 1514 + f: 1520 + f: 1526 + f: 1532 + f: 1538 + f: 1545 + f: 1551 + f: 1557 + f: 1564 + f: 1570 + f: 1576 + f: 1583 + f: 1589 + f: 1596 + f: 1602 + f: 1608 + f: 1615 + f: 1621 + f: 1628 + f: 1634 + f: 1641 + f: 1647 + f: 1654 + f: 1661 + f: 1667 + f: 1674 + f: 1681 + f: 1687 + f: 1694 + f: 1701 + f: 1708 + f: 1715 + f: 1722 + f: 1729 + f: 1735 + f: 1742 + f: 1749 + f: 1756 + f: 1763 + f: 1770 + f: 1777 + f: 1784 + f: 1791 + f: 1798 + f: 1806 + f: 1812 + f: 1820 + f: 1827 + f: 1835 + f: 1841 + f: 1849 + f: 1856 + f: 1863 + f: 1871 + f: 1878 + f: 1885 + f: 1893 + f: 1901 + f: 1908 + f: 1915 + f: 1923 + f: 1930 + f: 1938 + f: 1946 + f: 1953 + f: 1961 + f: 1969 + f: 1976 + f: 1984 + f: 1992 + f: 2000 + f: 2007 + f: 2015 + f: 2023 + f: 2031 + f: 2039 + f: 2047 + f: 2055 + f: 2063 + f: 2071 + f: 2079 + f: 2087 + f: 2095 + f: 2104 + f: 2112 + f: 2120 + f: 2128 + f: 2137 + f: 2146 + f: 2154 + f: 2162 + f: 2171 + f: 2179 + f: 2188 + f: 2197 + f: 2205 + f: 2214 + f: 2223 + f: 2232 + f: 2241 + f: 2250 + f: 2258 + f: 2268 + f: 2277 + f: 2285 + f: 2294 + f: 2304 + f: 2313 + f: 2322 + f: 2331 + f: 2340 + f: 2350 + f: 2359 + f: 2368 + f: 2378 + f: 2388 + f: 2397 + f: 2407 + f: 2416 + f: 2426 + f: 2436 + f: 2446 + f: 2455 + f: 2465 + f: 2475 + f: 2485 + f: 2495 + f: 2505 + f: 2515 + f: 2525 + f: 2535 + f: 2545 + f: 2556 + f: 2566 + f: 2577 + f: 2587 + f: 2598 + f: 2609 + f: 2620 + f: 2631 + f: 2641 + f: 2652 + f: 2663 + f: 2674 + f: 2685 + f: 2696 + f: 2708 + f: 2719 + f: 2730 + f: 2742 + f: 2753 + f: 2764 + f: 2776 + f: 2788 + f: 2799 + f: 2811 + f: 2823 + f: 2835 + f: 2847 + f: 2858 + f: 2870 + f: 2882 + f: 2894 + f: 2906 + f: 2919 + f: 2931 + f: 2943 + f: 2956 + f: 2968 + f: 2981 + f: 2994 + f: 3006 + f: 3019 + f: 3032 + f: 3045 + f: 3058 + f: 3070 + f: 3083 + f: 3096 + f: 3109 + f: 3121 + f: 3134 + f: 3148 + f: 3161 + f: 3174 + f: 3187 + f: 3200 + f: 3214 + f: 3228 + f: 3242 + f: 3255 + f: 3268 + f: 3283 + f: 3297 + f: 3310 + f: 3325 + f: 3340 + f: 3353 + f: 3368 + f: 3383 + f: 3398 + f: 3412 + f: 3427 + f: 3442 + f: 3457 + f: 3471 + f: 3487 + f: 3502 + f: 3516 + f: 3531 + f: 3546 + f: 3561 + f: 3577 + f: 3593 + f: 3608 + f: 3625 + f: 3641 + f: 3657 + f: 3673 + f: 3690 + f: 3706 + f: 3722 + f: 3738 + f: 3755 + f: 3772 + f: 3789 + f: 3805 + f: 3823 + f: 3839 + f: 3856 + f: 3873 + f: 3891 + f: 3908 + f: 3926 + f: 3944 + f: 3960 + f: 3977 + f: 3995 + f: 4013 + f: 4031 + f: 4048 + f: 4067 + f: 4085 + f: 4104 + f: 4122 + f: 4140 + f: 4159 + f: 4177 + f: 4196 + f: 4215 + f: 4234 + f: 4253 + f: 4272 + f: 4291 + f: 4311 + f: 4332 + f: 4351 + f: 4371 + f: 4391 + f: 4412 + f: 4433 + f: 4454 + f: 4474 + f: 4496 + f: 4518 + f: 4538 + f: 4558 + f: 4579 + f: 4601 + f: 4619 + f: 4640 + f: 4662 + f: 4684 + f: 4706 + f: 4728 + f: 4751 + f: 4771 + f: 4794 + f: 4818 + f: 4840 + f: 4863 + f: 4887 + f: 4910 + f: 4933 + f: 4956 + f: 4980 + f: 5004 + f: 5028 + f: 5052 + f: 5076 + f: 5100 + f: 5125 + f: 5152 + f: 5175 + f: 5200 + f: 5226 + f: 5251 + f: 5278 + f: 5304 + f: 5329 + f: 5354 + f: 5381 + f: 5407 + f: 5433 + f: 5460 + f: 5488 + f: 5516 + f: 5544 + f: 5573 + f: 5600 + f: 5628 + f: 5656 + f: 5684 + f: 5713 + f: 5741 + f: 5771 + f: 5799 + f: 5830 + f: 5860 + f: 5891 + f: 5921 + f: 5951 + f: 5980 + f: 6010 + f: 6041 + f: 6073 + f: 6105 + f: 6133 + f: 6163 + f: 6195 + f: 6227 + f: 6258 + f: 6291 + f: 6322 + f: 6356 + f: 6390 + f: 6424 + f: 6457 + f: 6491 + f: 6527 + f: 6561 + f: 6596 + f: 6631 + f: 6665 + f: 6701 + f: 6736 + f: 6771 + f: 6805 + f: 6840 + f: 6877 + f: 6911 + f: 6947 + f: 6985 + f: 7022 + f: 7059 + f: 7097 + f: 7135 + f: 7174 + f: 7212 + f: 7251 + f: 7289 + f: 7327 + f: 7366 + f: 7406 + f: 7447 + f: 7486 + f: 7525 + f: 7566 + f: 7606 + f: 7646 + f: 7688 + f: 7728 + f: 7771 + f: 7814 + f: 7859 + f: 7901 + f: 7949 + f: 7992 + f: 8036 + f: 8082 + f: 8127 + f: 8173 + f: 8218 + f: 8262 + f: 8309 + f: 8353 + f: 8397 + f: 8444 + f: 8489 + f: 8539 + f: 8585 + f: 8632 + f: 8682 + f: 8727 + f: 8777 + f: 8828 + f: 8879 + f: 8929 + f: 8982 + f: 9037 + f: 9087 + f: 9140 + f: 9193 + f: 9250 + f: 9305 + f: 9361 + f: 9418 + f: 9475 + f: 9532 + f: 9589 + f: 9644 + f: 9699 + f: 9758 + f: 9818 + f: 9875 + f: 9935 + f: 9997 + f: 10057 + f: 10117 + f: 10174 + f: 10232 + f: 10296 + f: 10356 + f: 10419 + f: 10482 + f: 10546 + f: 10608 + f: 10670 + f: 10729 + f: 10790 + f: 10855 + f: 10920 + f: 10990 + f: 11054 + f: 11118 + f: 11181 + f: 11248 + f: 11316 + f: 11385 + f: 11454 + f: 11526 + f: 11597 + f: 11667 + f: 11740 + f: 11820 + f: 11897 + f: 11973 + f: 12046 + f: 12126 + f: 12204 + f: 12287 + f: 12370 + f: 12456 + f: 12538 + f: 12627 + f: 12714 + f: 12799 + f: 12883 + f: 12971 + f: 13062 + f: 13154 + f: 13233 + f: 13328 + f: 13418 + f: 13511 + f: 13607 + f: 13709 + f: 13806 + f: 13903 + f: 14002 + f: 14104 + f: 14200 + f: 14288 + f: 14391 + f: 14488 + f: 14590 + f: 14698 + f: 14808 + f: 14910 + f: 15020 + f: 15126 + f: 15238 + f: 15347 + f: 15456 + f: 15574 + f: 15692 + f: 15786 + f: 15896 + f: 16016 + f: 16136 + f: 16250 + f: 16352 + f: 16474 + f: 16575 + f: 16702 + f: 16835 + f: 16965 + f: 17096 + f: 17232 + f: 17370 + f: 17443 + f: 17581 + f: 17719 + f: 17864 + f: 17976 + f: 18116 + f: 18250 + f: 18396 + f: 18540 + f: 18690 + f: 18840 + f: 18989 + f: 19136 + f: 19294 + f: 19445 + f: 19589 + f: 19750 + f: 19905 + f: 20064 + f: 20191 + f: 20325 + f: 20497 + f: 20662 + f: 20833 + f: 20981 + f: 21152 + f: 21334 + f: 21510 + f: 21642 + f: 21821 + f: 22001 + f: 22186 + f: 22379 + f: 22568 + f: 22770 + f: 22958 + f: 23162 + f: 23360 + f: 23524 + f: 23737 + f: 23960 + f: 24175 + f: 24395 + f: 24631 + f: 24865 + f: 25091 + f: 25327 + f: 25580 + f: 25833 + f: 26089 + f: 26361 + f: 26636 + f: 26889 + f: 27155 + f: 27436 + f: 27715 + f: 28003 + f: 28303 + f: 28600 + f: 28916 + f: 29223 + f: 29553 + f: 29884 + f: 30200 + f: 30538 + f: 30868 + f: 31211 + f: 31548 + f: 31881 + f: 32253 + f: 32605 + f: 32980 + f: 33385 + f: 33805 + f: 34254 + f: 34723 + f: 35167 + f: 35666 + f: 36125 + f: 36652 + f: 37177 + f: 37739 + f: 38321 + f: 38932 + f: 39640 + f: 40337 + f: 41000 + f: 41626 + f: 42385 + f: 43122 + f: 43890 + f: 44687 + f: 45609 + f: 46520 + f: 47489 + f: 48432 + f: 49458 + f: 50511 + f: 51561 + f: 52568 + f: 53676 + f: 54936 + f: 56071 + f: 57302 + f: 58513 + f: 59800 + f: 61192 + f: 62702 + f: 64205 + f: 65868 + f: 67780 + f: 69960 + f: 72330 + f: 74918 + f: 77540 + f: 80344 + f: 83727 + f: 87662 + f: 93589 + f: 101441 + f: 110544 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_8/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_8/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_8/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_8/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_8/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_8/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_8/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_8/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_8/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_8/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_8/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_8/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_9/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_9/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_9/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_12" + input: "QNetwork/EncodingNetwork/lambda_9/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_9/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_9/zeros_like" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + float_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_9/zeros_like" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_13" + input: "QNetwork/EncodingNetwork/lambda_10/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_10/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 13 + f: 38 + f: 56 + f: 70 + f: 82 + f: 94 + f: 104 + f: 114 + f: 123 + f: 131 + f: 139 + f: 148 + f: 152 + f: 153 + f: 158 + f: 163 + f: 170 + f: 174 + f: 178 + f: 180 + f: 183 + f: 186 + f: 188 + f: 190 + f: 192 + f: 196 + f: 198 + f: 201 + f: 205 + f: 208 + f: 212 + f: 215 + f: 219 + f: 221 + f: 225 + f: 227 + f: 229 + f: 232 + f: 233 + f: 236 + f: 239 + f: 242 + f: 245 + f: 248 + f: 250 + f: 252 + f: 254 + f: 256 + f: 259 + f: 261 + f: 264 + f: 267 + f: 270 + f: 272 + f: 275 + f: 278 + f: 280 + f: 283 + f: 285 + f: 287 + f: 290 + f: 293 + f: 295 + f: 297 + f: 300 + f: 303 + f: 305 + f: 308 + f: 311 + f: 313 + f: 316 + f: 319 + f: 322 + f: 325 + f: 329 + f: 331 + f: 333 + f: 336 + f: 338 + f: 340 + f: 343 + f: 345 + f: 347 + f: 347 + f: 349 + f: 351 + f: 353 + f: 355 + f: 357 + f: 359 + f: 361 + f: 363 + f: 365 + f: 368 + f: 369 + f: 371 + f: 373 + f: 375 + f: 377 + f: 380 + f: 382 + f: 385 + f: 387 + f: 389 + f: 391 + f: 394 + f: 396 + f: 398 + f: 400 + f: 403 + f: 405 + f: 408 + f: 410 + f: 412 + f: 415 + f: 417 + f: 420 + f: 422 + f: 425 + f: 427 + f: 429 + f: 432 + f: 434 + f: 437 + f: 439 + f: 442 + f: 444 + f: 446 + f: 449 + f: 451 + f: 454 + f: 456 + f: 458 + f: 461 + f: 463 + f: 466 + f: 469 + f: 472 + f: 474 + f: 476 + f: 479 + f: 482 + f: 483 + f: 486 + f: 489 + f: 492 + f: 495 + f: 498 + f: 500 + f: 503 + f: 505 + f: 508 + f: 510 + f: 513 + f: 516 + f: 519 + f: 522 + f: 524 + f: 528 + f: 530 + f: 533 + f: 536 + f: 539 + f: 541 + f: 544 + f: 547 + f: 550 + f: 553 + f: 556 + f: 559 + f: 561 + f: 563 + f: 567 + f: 570 + f: 572 + f: 575 + f: 577 + f: 580 + f: 584 + f: 586 + f: 589 + f: 592 + f: 595 + f: 598 + f: 601 + f: 605 + f: 607 + f: 611 + f: 613 + f: 617 + f: 620 + f: 623 + f: 626 + f: 629 + f: 632 + f: 635 + f: 639 + f: 642 + f: 645 + f: 648 + f: 651 + f: 654 + f: 657 + f: 660 + f: 662 + f: 666 + f: 669 + f: 672 + f: 676 + f: 679 + f: 682 + f: 685 + f: 688 + f: 690 + f: 693 + f: 696 + f: 699 + f: 702 + f: 705 + f: 709 + f: 712 + f: 714 + f: 718 + f: 721 + f: 724 + f: 726 + f: 728 + f: 729 + f: 731 + f: 734 + f: 737 + f: 741 + f: 745 + f: 748 + f: 750 + f: 753 + f: 756 + f: 760 + f: 763 + f: 766 + f: 770 + f: 773 + f: 776 + f: 779 + f: 782 + f: 786 + f: 788 + f: 793 + f: 796 + f: 798 + f: 802 + f: 805 + f: 808 + f: 811 + f: 815 + f: 818 + f: 820 + f: 824 + f: 827 + f: 829 + f: 832 + f: 835 + f: 838 + f: 842 + f: 846 + f: 849 + f: 854 + f: 857 + f: 860 + f: 864 + f: 867 + f: 871 + f: 875 + f: 879 + f: 882 + f: 887 + f: 890 + f: 893 + f: 897 + f: 901 + f: 905 + f: 908 + f: 911 + f: 915 + f: 918 + f: 921 + f: 925 + f: 929 + f: 932 + f: 934 + f: 937 + f: 940 + f: 943 + f: 946 + f: 950 + f: 953 + f: 956 + f: 961 + f: 965 + f: 969 + f: 973 + f: 976 + f: 980 + f: 982 + f: 985 + f: 990 + f: 994 + f: 997 + f: 1001 + f: 1005 + f: 1007 + f: 1010 + f: 1014 + f: 1018 + f: 1022 + f: 1025 + f: 1028 + f: 1033 + f: 1035 + f: 1038 + f: 1042 + f: 1047 + f: 1052 + f: 1056 + f: 1060 + f: 1063 + f: 1067 + f: 1071 + f: 1075 + f: 1079 + f: 1083 + f: 1086 + f: 1088 + f: 1092 + f: 1097 + f: 1102 + f: 1106 + f: 1109 + f: 1113 + f: 1117 + f: 1120 + f: 1125 + f: 1129 + f: 1134 + f: 1137 + f: 1142 + f: 1146 + f: 1150 + f: 1151 + f: 1155 + f: 1159 + f: 1162 + f: 1166 + f: 1170 + f: 1174 + f: 1177 + f: 1181 + f: 1185 + f: 1188 + f: 1193 + f: 1196 + f: 1203 + f: 1207 + f: 1212 + f: 1214 + f: 1217 + f: 1220 + f: 1222 + f: 1222 + f: 1226 + f: 1229 + f: 1233 + f: 1237 + f: 1241 + f: 1246 + f: 1250 + f: 1253 + f: 1257 + f: 1262 + f: 1267 + f: 1272 + f: 1278 + f: 1283 + f: 1287 + f: 1293 + f: 1297 + f: 1301 + f: 1304 + f: 1309 + f: 1315 + f: 1320 + f: 1325 + f: 1329 + f: 1333 + f: 1336 + f: 1341 + f: 1344 + f: 1348 + f: 1351 + f: 1357 + f: 1363 + f: 1368 + f: 1374 + f: 1379 + f: 1383 + f: 1386 + f: 1391 + f: 1395 + f: 1399 + f: 1403 + f: 1407 + f: 1410 + f: 1415 + f: 1418 + f: 1423 + f: 1428 + f: 1432 + f: 1436 + f: 1438 + f: 1442 + f: 1446 + f: 1450 + f: 1454 + f: 1462 + f: 1467 + f: 1472 + f: 1477 + f: 1483 + f: 1488 + f: 1492 + f: 1496 + f: 1503 + f: 1508 + f: 1513 + f: 1518 + f: 1520 + f: 1526 + f: 1531 + f: 1534 + f: 1538 + f: 1542 + f: 1546 + f: 1552 + f: 1558 + f: 1564 + f: 1568 + f: 1573 + f: 1578 + f: 1581 + f: 1590 + f: 1596 + f: 1601 + f: 1606 + f: 1611 + f: 1616 + f: 1622 + f: 1629 + f: 1634 + f: 1640 + f: 1647 + f: 1651 + f: 1657 + f: 1660 + f: 1665 + f: 1672 + f: 1678 + f: 1686 + f: 1692 + f: 1698 + f: 1704 + f: 1709 + f: 1714 + f: 1719 + f: 1724 + f: 1730 + f: 1737 + f: 1744 + f: 1751 + f: 1755 + f: 1761 + f: 1764 + f: 1772 + f: 1778 + f: 1784 + f: 1789 + f: 1799 + f: 1804 + f: 1811 + f: 1819 + f: 1825 + f: 1830 + f: 1838 + f: 1849 + f: 1858 + f: 1862 + f: 1868 + f: 1872 + f: 1878 + f: 1885 + f: 1888 + f: 1892 + f: 1897 + f: 1902 + f: 1907 + f: 1919 + f: 1926 + f: 1932 + f: 1936 + f: 1941 + f: 1946 + f: 1952 + f: 1960 + f: 1968 + f: 1977 + f: 1985 + f: 1992 + f: 1997 + f: 2006 + f: 2012 + f: 2018 + f: 2026 + f: 2034 + f: 2044 + f: 2050 + f: 2057 + f: 2064 + f: 2069 + f: 2075 + f: 2082 + f: 2091 + f: 2098 + f: 2107 + f: 2122 + f: 2126 + f: 2135 + f: 2146 + f: 2149 + f: 2157 + f: 2163 + f: 2172 + f: 2178 + f: 2184 + f: 2191 + f: 2198 + f: 2208 + f: 2216 + f: 2223 + f: 2235 + f: 2242 + f: 2252 + f: 2263 + f: 2272 + f: 2277 + f: 2288 + f: 2296 + f: 2306 + f: 2311 + f: 2318 + f: 2323 + f: 2334 + f: 2341 + f: 2356 + f: 2366 + f: 2373 + f: 2379 + f: 2386 + f: 2407 + f: 2416 + f: 2423 + f: 2432 + f: 2438 + f: 2448 + f: 2453 + f: 2464 + f: 2473 + f: 2473 + f: 2481 + f: 2492 + f: 2504 + f: 2511 + f: 2523 + f: 2529 + f: 2537 + f: 2545 + f: 2556 + f: 2566 + f: 2575 + f: 2584 + f: 2592 + f: 2602 + f: 2613 + f: 2624 + f: 2636 + f: 2643 + f: 2647 + f: 2652 + f: 2664 + f: 2675 + f: 2688 + f: 2693 + f: 2702 + f: 2709 + f: 2722 + f: 2739 + f: 2754 + f: 2766 + f: 2776 + f: 2786 + f: 2799 + f: 2810 + f: 2832 + f: 2840 + f: 2849 + f: 2860 + f: 2873 + f: 2889 + f: 2908 + f: 2914 + f: 2926 + f: 2939 + f: 2950 + f: 2961 + f: 2969 + f: 2978 + f: 2990 + f: 2999 + f: 3023 + f: 3032 + f: 3049 + f: 3066 + f: 3085 + f: 3101 + f: 3107 + f: 3117 + f: 3129 + f: 3144 + f: 3167 + f: 3190 + f: 3212 + f: 3229 + f: 3238 + f: 3264 + f: 3293 + f: 3302 + f: 3309 + f: 3314 + f: 3323 + f: 3344 + f: 3352 + f: 3362 + f: 3390 + f: 3400 + f: 3411 + f: 3435 + f: 3456 + f: 3470 + f: 3485 + f: 3498 + f: 3505 + f: 3519 + f: 3539 + f: 3545 + f: 3545 + f: 3560 + f: 3576 + f: 3597 + f: 3607 + f: 3621 + f: 3641 + f: 3665 + f: 3679 + f: 3701 + f: 3714 + f: 3733 + f: 3741 + f: 3745 + f: 3757 + f: 3773 + f: 3787 + f: 3795 + f: 3805 + f: 3822 + f: 3835 + f: 3844 + f: 3861 + f: 3872 + f: 3878 + f: 3897 + f: 3919 + f: 3941 + f: 3971 + f: 4004 + f: 4014 + f: 4019 + f: 4061 + f: 4068 + f: 4089 + f: 4108 + f: 4117 + f: 4125 + f: 4146 + f: 4165 + f: 4194 + f: 4204 + f: 4224 + f: 4236 + f: 4263 + f: 4290 + f: 4301 + f: 4319 + f: 4326 + f: 4347 + f: 4369 + f: 4386 + f: 4413 + f: 4435 + f: 4451 + f: 4451 + f: 4451 + f: 4476 + f: 4500 + f: 4539 + f: 4579 + f: 4592 + f: 4600 + f: 4622 + f: 4650 + f: 4683 + f: 4714 + f: 4742 + f: 4755 + f: 4771 + f: 4788 + f: 4816 + f: 4828 + f: 4831 + f: 4831 + f: 4831 + f: 4843 + f: 4852 + f: 4865 + f: 4896 + f: 4915 + f: 4931 + f: 4952 + f: 4965 + f: 4983 + f: 5007 + f: 5043 + f: 5061 + f: 5081 + f: 5095 + f: 5122 + f: 5143 + f: 5171 + f: 5204 + f: 5226 + f: 5233 + f: 5250 + f: 5281 + f: 5320 + f: 5323 + f: 5328 + f: 5345 + f: 5374 + f: 5413 + f: 5466 + f: 5492 + f: 5524 + f: 5555 + f: 5567 + f: 5610 + f: 5676 + f: 5701 + f: 5716 + f: 5744 + f: 5768 + f: 5795 + f: 5818 + f: 5854 + f: 5906 + f: 5934 + f: 5960 + f: 5975 + f: 5993 + f: 6025 + f: 6034 + f: 6051 + f: 6082 + f: 6106 + f: 6125 + f: 6159 + f: 6187 + f: 6242 + f: 6287 + f: 6311 + f: 6332 + f: 6348 + f: 6358 + f: 6368 + f: 6377 + f: 6402 + f: 6407 + f: 6428 + f: 6450 + f: 6475 + f: 6498 + f: 6505 + f: 6533 + f: 6565 + f: 6580 + f: 6595 + f: 6611 + f: 6654 + f: 6658 + f: 6705 + f: 6751 + f: 6786 + f: 6828 + f: 6876 + f: 6896 + f: 6948 + f: 6964 + f: 7065 + f: 7082 + f: 7118 + f: 7184 + f: 7214 + f: 7271 + f: 7310 + f: 7357 + f: 7405 + f: 7506 + f: 7613 + f: 7641 + f: 7675 + f: 7720 + f: 7781 + f: 7833 + f: 7860 + f: 7898 + f: 7929 + f: 8044 + f: 8104 + f: 8148 + f: 8236 + f: 8273 + f: 8313 + f: 8349 + f: 8381 + f: 8409 + f: 8498 + f: 8507 + f: 8524 + f: 8570 + f: 8607 + f: 8630 + f: 8637 + f: 8675 + f: 8700 + f: 8714 + f: 8734 + f: 8776 + f: 8836 + f: 8854 + f: 8867 + f: 8868 + f: 9065 + f: 9113 + f: 9121 + f: 9241 + f: 9357 + f: 9360 + f: 9585 + f: 9613 + f: 9684 + f: 9727 + f: 9751 + f: 9777 + f: 9802 + f: 9889 + f: 9903 + f: 9914 + f: 9978 + f: 10061 + f: 10192 + f: 10213 + f: 10345 + f: 10369 + f: 10404 + f: 10430 + f: 10471 + f: 10481 + f: 10489 + f: 10492 + f: 10494 + f: 10524 + f: 10554 + f: 10557 + f: 10560 + f: 10562 + f: 10641 + f: 10716 + f: 10842 + f: 10897 + f: 10967 + f: 11053 + f: 11128 + f: 11137 + f: 11328 + f: 11336 + f: 11401 + f: 11532 + f: 11573 + f: 11860 + f: 11880 + f: 12013 + f: 12305 + f: 12358 + f: 12386 + f: 12404 + f: 12456 + f: 12456 + f: 12476 + f: 12615 + f: 12677 + f: 12981 + f: 13094 + f: 13197 + f: 13708 + f: 13717 + f: 13788 + f: 14049 + f: 14112 + f: 14224 + f: 14257 + f: 14681 + f: 14901 + f: 15006 + f: 15071 + f: 15100 + f: 15248 + f: 15669 + f: 15877 + f: 15953 + f: 15953 + f: 16066 + f: 16072 + f: 16271 + f: 16292 + f: 16386 + f: 16490 + f: 16633 + f: 16670 + f: 16834 + f: 16896 + f: 17543 + f: 17693 + f: 17800 + f: 17859 + f: 18397 + f: 18811 + f: 18826 + f: 18971 + f: 19304 + f: 19319 + f: 19695 + f: 20378 + f: 20865 + f: 21313 + f: 21330 + f: 22321 + f: 22760 + f: 22770 + f: 23783 + f: 23785 + f: 24525 + f: 24844 + f: 24848 + f: 24964 + f: 24966 + f: 27468 + f: 27478 + f: 27555 + f: 27555 + f: 28215 + f: 28219 + f: 28336 + f: 28490 + f: 30213 + f: 30228 + f: 30242 + f: 34116 + f: 43518 + f: 43518 + f: 43518 + f: 43852 + f: 43852 + f: 43852 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_10/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_10/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_10/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_10/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_10/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_10/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_10/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_10/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_10/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_10/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_10/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_10/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/expand_dims/ExpandDims/dim" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/expand_dims/ExpandDims/dim" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/expand_dims/ExpandDims" + op: "ExpandDims" + input: "time_step_14" + input: "QNetwork/EncodingNetwork/lambda_11/expand_dims/ExpandDims/dim:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/expand_dims/ExpandDims" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/Bucketize" + op: "Bucketize" + input: "QNetwork/EncodingNetwork/lambda_11/expand_dims/ExpandDims:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "boundaries" + value { + list { + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 0 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 1 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 2 + f: 3 + f: 4 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/Bucketize" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/Cast" + op: "Cast" + input: "QNetwork/EncodingNetwork/lambda_11/Bucketize:output:0" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/Cast" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/truediv/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + } + float_val: 999 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/truediv/y" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/truediv" + op: "RealDiv" + input: "QNetwork/EncodingNetwork/lambda_11/Cast:y:0" + input: "QNetwork/EncodingNetwork/lambda_11/truediv/y:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/truediv" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/Sqrt" + op: "Sqrt" + input: "QNetwork/EncodingNetwork/lambda_11/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/Sqrt" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/mul" + op: "Mul" + input: "QNetwork/EncodingNetwork/lambda_11/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_11/truediv:z:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/mul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/lambda_11/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda_11/truediv:z:0" + input: "QNetwork/EncodingNetwork/lambda_11/Sqrt:y:0" + input: "QNetwork/EncodingNetwork/lambda_11/mul:z:0" + input: "QNetwork/EncodingNetwork/lambda_11/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 3 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/lambda_11/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/concatenate/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 1 + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/concatenate/concat/axis" + } + } + node_def { + name: "QNetwork/EncodingNetwork/concatenate/concat" + op: "ConcatV2" + input: "QNetwork/EncodingNetwork/lambda/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_1/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_2/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_3/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_4/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_5/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_6/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_7/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_8/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_9/zeros_like:output:0" + input: "QNetwork/EncodingNetwork/lambda_10/concat:output:0" + input: "QNetwork/EncodingNetwork/lambda_11/concat:output:0" + input: "QNetwork/EncodingNetwork/concatenate/concat/axis:output:0" + attr { + key: "N" + value { + i: 12 + } + } + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 34 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/concatenate/concat" + } + } + node_def { + name: "QNetwork/EncodingNetwork/flatten/Const" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 2 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + size: 2 + } + } + tensor_content: "\377\377\377\377\"\000\000\000" + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/flatten/Const" + } + } + node_def { + name: "QNetwork/EncodingNetwork/flatten/Reshape" + op: "Reshape" + input: "QNetwork/EncodingNetwork/concatenate/concat:output:0" + input: "QNetwork/EncodingNetwork/flatten/Const:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 34 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/flatten/Reshape" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "qnetwork_encodingnetwork_dense_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 34 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense/MatMul/ReadVariableOp" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense/MatMul" + op: "MatMul" + input: "QNetwork/EncodingNetwork/flatten/Reshape:output:0" + input: "QNetwork/EncodingNetwork/dense/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense/MatMul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "qnetwork_encodingnetwork_dense_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense/BiasAdd" + op: "BiasAdd" + input: "QNetwork/EncodingNetwork/dense/MatMul:product:0" + input: "QNetwork/EncodingNetwork/dense/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense/BiasAdd" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense/Relu" + op: "Relu" + input: "QNetwork/EncodingNetwork/dense/BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense/Relu" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense_1/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "qnetwork_encodingnetwork_dense_1_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 40 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense_1/MatMul/ReadVariableOp" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense_1/MatMul" + op: "MatMul" + input: "QNetwork/EncodingNetwork/dense/Relu:activations:0" + input: "QNetwork/EncodingNetwork/dense_1/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 40 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense_1/MatMul" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense_1/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "qnetwork_encodingnetwork_dense_1_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 40 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense_1/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense_1/BiasAdd" + op: "BiasAdd" + input: "QNetwork/EncodingNetwork/dense_1/MatMul:product:0" + input: "QNetwork/EncodingNetwork/dense_1/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 40 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense_1/BiasAdd" + } + } + node_def { + name: "QNetwork/EncodingNetwork/dense_1/Relu" + op: "Relu" + input: "QNetwork/EncodingNetwork/dense_1/BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 40 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/EncodingNetwork/dense_1/Relu" + } + } + node_def { + name: "QNetwork/dense_2/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "qnetwork_dense_2_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 40 + } + dim { + size: 2 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "QNetwork/dense_2/MatMul/ReadVariableOp" + } + } + node_def { + name: "QNetwork/dense_2/MatMul" + op: "MatMul" + input: "QNetwork/EncodingNetwork/dense_1/Relu:activations:0" + input: "QNetwork/dense_2/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 2 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/dense_2/MatMul" + } + } + node_def { + name: "QNetwork/dense_2/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "qnetwork_dense_2_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 2 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "QNetwork/dense_2/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "QNetwork/dense_2/BiasAdd" + op: "BiasAdd" + input: "QNetwork/dense_2/MatMul:product:0" + input: "QNetwork/dense_2/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 2 + } + } + } + } + } + experimental_debug_info { + original_node_names: "QNetwork/dense_2/BiasAdd" + } + } + node_def { + name: "ShiftedCategorical_1/mode/ArgMax/dimension" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: -1 + } + } + } + experimental_debug_info { + original_node_names: "ShiftedCategorical_1/mode/ArgMax/dimension" + } + } + node_def { + name: "ShiftedCategorical_1/mode/ArgMax" + op: "ArgMax" + input: "QNetwork/dense_2/BiasAdd:output:0" + input: "ShiftedCategorical_1/mode/ArgMax/dimension:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "ShiftedCategorical_1/mode/ArgMax" + } + } + node_def { + name: "add/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT64 + tensor_shape { + } + int64_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "add/y" + } + } + node_def { + name: "add" + op: "AddV2" + input: "ShiftedCategorical_1/mode/ArgMax:output:0" + input: "add/y:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "add" + } + } + node_def { + name: "Deterministic/atol" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT64 + tensor_shape { + } + int64_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic/atol" + } + } + node_def { + name: "Deterministic/rtol" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT64 + tensor_shape { + } + int64_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic/rtol" + } + } + node_def { + name: "Deterministic_1/sample/sample_shape/x" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_FLOAT + tensor_shape { + dim { + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/sample_shape/x" + } + } + node_def { + name: "Deterministic_1/sample/sample_shape" + op: "Cast" + input: "Deterministic_1/sample/sample_shape/x:output:0" + attr { + key: "DstT" + value { + type: DT_INT32 + } + } + attr { + key: "SrcT" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/sample_shape" + } + } + node_def { + name: "Deterministic_1/sample/Shape" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + size: 1 + } + } + int_val: 1 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/Shape" + } + } + node_def { + name: "Deterministic_1/sample/Shape_1" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/Shape_1" + } + } + node_def { + name: "Deterministic_1/sample/Shape_2" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/Shape_2" + } + } + node_def { + name: "Deterministic_1/sample/BroadcastArgs" + op: "BroadcastArgs" + input: "Deterministic_1/sample/Shape_1:output:0" + input: "Deterministic_1/sample/Shape_2:output:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/BroadcastArgs" + } + } + node_def { + name: "Deterministic_1/sample/BroadcastArgs_1" + op: "BroadcastArgs" + input: "Deterministic_1/sample/Shape:output:0" + input: "Deterministic_1/sample/BroadcastArgs:r0:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/BroadcastArgs_1" + } + } + node_def { + name: "Deterministic_1/sample/Const" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/Const" + } + } + node_def { + name: "Deterministic_1/sample/concat/values_0" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + size: 1 + } + } + int_val: 1 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/concat/values_0" + } + } + node_def { + name: "Deterministic_1/sample/concat/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/concat/axis" + } + } + node_def { + name: "Deterministic_1/sample/concat" + op: "ConcatV2" + input: "Deterministic_1/sample/concat/values_0:output:0" + input: "Deterministic_1/sample/BroadcastArgs_1:r0:0" + input: "Deterministic_1/sample/Const:output:0" + input: "Deterministic_1/sample/concat/axis:output:0" + attr { + key: "N" + value { + i: 3 + } + } + attr { + key: "T" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 2 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/concat" + } + } + node_def { + name: "Deterministic_1/sample/BroadcastTo" + op: "BroadcastTo" + input: "add:z:0" + input: "Deterministic_1/sample/concat:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/BroadcastTo" + } + } + node_def { + name: "Deterministic_1/sample/Shape_3" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 2 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + size: 2 + } + } + tensor_content: "\001\000\000\000\001\000\000\000" + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/Shape_3" + } + } + node_def { + name: "Deterministic_1/sample/strided_slice/stack" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + size: 1 + } + } + int_val: 1 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/strided_slice/stack" + } + } + node_def { + name: "Deterministic_1/sample/strided_slice/stack_1" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + size: 1 + } + } + int_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/strided_slice/stack_1" + } + } + node_def { + name: "Deterministic_1/sample/strided_slice/stack_2" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + dim { + size: 1 + } + } + int_val: 1 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/strided_slice/stack_2" + } + } + node_def { + name: "Deterministic_1/sample/strided_slice" + op: "StridedSlice" + input: "Deterministic_1/sample/Shape_3:output:0" + input: "Deterministic_1/sample/strided_slice/stack:output:0" + input: "Deterministic_1/sample/strided_slice/stack_1:output:0" + input: "Deterministic_1/sample/strided_slice/stack_2:output:0" + attr { + key: "Index" + value { + type: DT_INT32 + } + } + attr { + key: "T" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "end_mask" + value { + i: 1 + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/strided_slice" + } + } + node_def { + name: "Deterministic_1/sample/concat_1/axis" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/concat_1/axis" + } + } + node_def { + name: "Deterministic_1/sample/concat_1" + op: "ConcatV2" + input: "Deterministic_1/sample/sample_shape:y:0" + input: "Deterministic_1/sample/strided_slice:output:0" + input: "Deterministic_1/sample/concat_1/axis:output:0" + attr { + key: "N" + value { + i: 2 + } + } + attr { + key: "T" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/concat_1" + } + } + node_def { + name: "Deterministic_1/sample/Reshape" + op: "Reshape" + input: "Deterministic_1/sample/BroadcastTo:output:0" + input: "Deterministic_1/sample/concat_1:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Deterministic_1/sample/Reshape" + } + } + node_def { + name: "clip_by_value/Minimum/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT64 + tensor_shape { + } + int64_val: 1 + } + } + } + experimental_debug_info { + original_node_names: "clip_by_value/Minimum/y" + } + } + node_def { + name: "clip_by_value/Minimum" + op: "Minimum" + input: "Deterministic_1/sample/Reshape:output:0" + input: "clip_by_value/Minimum/y:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "clip_by_value/Minimum" + } + } + node_def { + name: "clip_by_value/y" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT64 + tensor_shape { + } + int64_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "clip_by_value/y" + } + } + node_def { + name: "clip_by_value" + op: "Maximum" + input: "clip_by_value/Minimum:z:0" + input: "clip_by_value/y:output:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "clip_by_value" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "clip_by_value:z:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 9 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 10 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 11 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 12 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 13 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 14 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 15 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 16 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 17 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 18 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 19 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 20 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_signature_wrapper_4619033" + } + node_def { + name: "PartitionedCall" + op: "PartitionedCall" + attr { + key: "Tin" + value { + list { + } + } + } + attr { + key: "Tout" + value { + list { + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_function_with_signature_4619029" + } + } + } + experimental_debug_info { + original_node_names: "PartitionedCall" + } + } + attr { + key: "_input_shapes" + value { + } + } + } + function { + signature { + name: "__inference__traced_save_4619143" + input_arg { + name: "file_prefix" + type: DT_STRING + } + input_arg { + name: "savev2_train_step_read_readvariableop" + type: DT_INT64 + } + input_arg { + name: "savev2_qnetwork_encodingnetwork_dense_kernel_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_qnetwork_encodingnetwork_dense_bias_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_qnetwork_encodingnetwork_dense_1_kernel_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_qnetwork_encodingnetwork_dense_1_bias_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_qnetwork_dense_2_kernel_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_qnetwork_dense_2_bias_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_1_const" + type: DT_STRING + } + output_arg { + name: "identity_1" + type: DT_STRING + } + is_stateful: true + control_output: "MergeV2Checkpoints" + control_output: "SaveV2" + control_output: "SaveV2_1" + } + node_def { + name: "StaticRegexFullMatch" + op: "StaticRegexFullMatch" + input: "file_prefix" + device: "/device:CPU:*" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "pattern" + value { + s: "^s3://.*" + } + } + experimental_debug_info { + original_node_names: "StaticRegexFullMatch" + } + } + node_def { + name: "Const" + op: "Const" + device: "/device:CPU:*" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + } + string_val: ".part" + } + } + } + experimental_debug_info { + original_node_names: "Const" + } + } + node_def { + name: "Const_1" + op: "Const" + device: "/device:CPU:*" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + } + string_val: "_temp_f4c8d2e64931472295be68a11e57e937/part" + } + } + } + experimental_debug_info { + original_node_names: "Const_1" + } + } + node_def { + name: "Select" + op: "Select" + input: "StaticRegexFullMatch:output:0" + input: "Const:output:0" + input: "Const_1:output:0" + device: "/device:CPU:*" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Select" + } + } + node_def { + name: "StringJoin" + op: "StringJoin" + input: "file_prefix" + input: "Select:output:0" + device: "/device:CPU:*" + attr { + key: "N" + value { + i: 2 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "StringJoin" + } + } + node_def { + name: "num_shards" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 2 + } + } + } + experimental_debug_info { + original_node_names: "num_shards" + } + } + node_def { + name: "ShardedFilename/shard" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "ShardedFilename/shard" + } + } + node_def { + name: "ShardedFilename" + op: "ShardedFilename" + input: "StringJoin:output:0" + input: "ShardedFilename/shard:output:0" + input: "num_shards:output:0" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "ShardedFilename" + } + } + node_def { + name: "SaveV2/tensor_names" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 7 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 7 + } + } + string_val: "train_step/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/0/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/1/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/2/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/3/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/4/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/5/.ATTRIBUTES/VARIABLE_VALUE" + } + } + } + experimental_debug_info { + original_node_names: "SaveV2/tensor_names" + } + } + node_def { + name: "SaveV2/shape_and_slices" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 7 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 7 + } + } + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + } + } + } + experimental_debug_info { + original_node_names: "SaveV2/shape_and_slices" + } + } + node_def { + name: "SaveV2" + op: "SaveV2" + input: "ShardedFilename:filename:0" + input: "SaveV2/tensor_names:output:0" + input: "SaveV2/shape_and_slices:output:0" + input: "savev2_train_step_read_readvariableop" + input: "savev2_qnetwork_encodingnetwork_dense_kernel_read_readvariableop" + input: "savev2_qnetwork_encodingnetwork_dense_bias_read_readvariableop" + input: "savev2_qnetwork_encodingnetwork_dense_1_kernel_read_readvariableop" + input: "savev2_qnetwork_encodingnetwork_dense_1_bias_read_readvariableop" + input: "savev2_qnetwork_dense_2_kernel_read_readvariableop" + input: "savev2_qnetwork_dense_2_bias_read_readvariableop" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtypes" + value { + list { + type: DT_INT64 + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + } + } + } + experimental_debug_info { + original_node_names: "SaveV2" + } + } + node_def { + name: "ShardedFilename_1/shard" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 1 + } + } + } + experimental_debug_info { + original_node_names: "ShardedFilename_1/shard" + } + } + node_def { + name: "ShardedFilename_1" + op: "ShardedFilename" + input: "StringJoin:output:0" + input: "ShardedFilename_1/shard:output:0" + input: "num_shards:output:0" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "ShardedFilename_1" + } + } + node_def { + name: "SaveV2_1/tensor_names" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 1 + } + } + string_val: "_CHECKPOINTABLE_OBJECT_GRAPH" + } + } + } + experimental_debug_info { + original_node_names: "SaveV2_1/tensor_names" + } + } + node_def { + name: "SaveV2_1/shape_and_slices" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 1 + } + } + string_val: "" + } + } + } + experimental_debug_info { + original_node_names: "SaveV2_1/shape_and_slices" + } + } + node_def { + name: "SaveV2_1" + op: "SaveV2" + input: "ShardedFilename_1:filename:0" + input: "SaveV2_1/tensor_names:output:0" + input: "SaveV2_1/shape_and_slices:output:0" + input: "savev2_1_const" + input: "^SaveV2" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtypes" + value { + list { + type: DT_STRING + } + } + } + experimental_debug_info { + original_node_names: "SaveV2_1" + } + } + node_def { + name: "MergeV2Checkpoints/checkpoint_prefixes" + op: "Pack" + input: "ShardedFilename:filename:0" + input: "ShardedFilename_1:filename:0" + input: "^SaveV2" + input: "^SaveV2_1" + device: "/device:CPU:0" + attr { + key: "N" + value { + i: 2 + } + } + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 2 + } + } + } + } + } + experimental_debug_info { + original_node_names: "MergeV2Checkpoints/checkpoint_prefixes" + } + } + node_def { + name: "MergeV2Checkpoints" + op: "MergeV2Checkpoints" + input: "MergeV2Checkpoints/checkpoint_prefixes:output:0" + input: "file_prefix" + input: "^SaveV2_1" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + experimental_debug_info { + original_node_names: "MergeV2Checkpoints" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "file_prefix" + input: "^MergeV2Checkpoints" + device: "/device:CPU:0" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + node_def { + name: "Identity_1" + op: "Identity" + input: "Identity:output:0" + input: "^MergeV2Checkpoints" + input: "^SaveV2" + input: "^SaveV2_1" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_1" + } + } + ret { + key: "identity_1" + value: "Identity_1:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + } + shape { + } + shape { + dim { + size: 34 + } + dim { + size: 100 + } + } + shape { + dim { + size: 100 + } + } + shape { + dim { + size: 100 + } + dim { + size: 40 + } + } + shape { + dim { + size: 40 + } + } + shape { + dim { + size: 40 + } + dim { + size: 2 + } + } + shape { + dim { + size: 2 + } + } + shape { + } + } + } + } + control_ret { + key: "MergeV2Checkpoints" + value: "MergeV2Checkpoints" + } + control_ret { + key: "SaveV2" + value: "SaveV2" + } + control_ret { + key: "SaveV2_1" + value: "SaveV2_1" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "file_prefix" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 34 + } + dim { + size: 100 + } + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 40 + } + } + } + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 40 + } + } + } + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 40 + } + dim { + size: 2 + } + } + } + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 2 + } + } + } + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_function_722" + } + attr { + key: "_input_shapes" + value { + } + } + } + function { + signature { + name: "__inference_signature_wrapper_4619026" + input_arg { + name: "callee_basic_block_count" + type: DT_INT64 + } + input_arg { + name: "callee_conditionally_executed_blocks" + type: DT_INT64 + } + input_arg { + name: "callee_users" + type: DT_INT64 + } + input_arg { + name: "caller_basic_block_count" + type: DT_INT64 + } + input_arg { + name: "caller_conditionally_executed_blocks" + type: DT_INT64 + } + input_arg { + name: "caller_users" + type: DT_INT64 + } + input_arg { + name: "callsite_height" + type: DT_INT64 + } + input_arg { + name: "cost_estimate" + type: DT_INT64 + } + input_arg { + name: "discount" + type: DT_FLOAT + } + input_arg { + name: "edge_count" + type: DT_INT64 + } + input_arg { + name: "inlining_default" + type: DT_INT64 + } + input_arg { + name: "node_count" + type: DT_INT64 + } + input_arg { + name: "nr_ctant_params" + type: DT_INT64 + } + input_arg { + name: "reward" + type: DT_FLOAT + } + input_arg { + name: "step_type" + type: DT_INT32 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + input_arg { + name: "unknown_3" + type: DT_RESOURCE + } + input_arg { + name: "unknown_4" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "step_type" + input: "reward" + input: "discount" + input: "callee_basic_block_count" + input: "callee_conditionally_executed_blocks" + input: "callee_users" + input: "caller_basic_block_count" + input: "caller_conditionally_executed_blocks" + input: "caller_users" + input: "callsite_height" + input: "cost_estimate" + input: "edge_count" + input: "inlining_default" + input: "node_count" + input: "nr_ctant_params" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + input: "unknown_3" + input: "unknown_4" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_FLOAT + type: DT_FLOAT + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 15 + i: 16 + i: 17 + i: 18 + i: 19 + i: 20 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_function_with_signature_4618993" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_basic_block_count" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_conditionally_executed_blocks" + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_users" + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_basic_block_count" + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_conditionally_executed_blocks" + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_users" + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callsite_height" + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "cost_estimate" + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "discount" + } + } + } + } + arg_attr { + key: 9 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "edge_count" + } + } + } + } + arg_attr { + key: 10 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inlining_default" + } + } + } + } + arg_attr { + key: 11 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "node_count" + } + } + } + } + arg_attr { + key: 12 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "nr_ctant_params" + } + } + } + } + arg_attr { + key: 13 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "reward" + } + } + } + } + arg_attr { + key: 14 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "step_type" + } + } + } + } + arg_attr { + key: 15 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 16 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 17 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 18 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 19 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 20 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_function_with_signature_4618993" + input_arg { + name: "step_type" + type: DT_INT32 + } + input_arg { + name: "reward" + type: DT_FLOAT + } + input_arg { + name: "discount" + type: DT_FLOAT + } + input_arg { + name: "callee_basic_block_count" + type: DT_INT64 + } + input_arg { + name: "callee_conditionally_executed_blocks" + type: DT_INT64 + } + input_arg { + name: "callee_users" + type: DT_INT64 + } + input_arg { + name: "caller_basic_block_count" + type: DT_INT64 + } + input_arg { + name: "caller_conditionally_executed_blocks" + type: DT_INT64 + } + input_arg { + name: "caller_users" + type: DT_INT64 + } + input_arg { + name: "callsite_height" + type: DT_INT64 + } + input_arg { + name: "cost_estimate" + type: DT_INT64 + } + input_arg { + name: "edge_count" + type: DT_INT64 + } + input_arg { + name: "inlining_default" + type: DT_INT64 + } + input_arg { + name: "node_count" + type: DT_INT64 + } + input_arg { + name: "nr_ctant_params" + type: DT_INT64 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + input_arg { + name: "unknown_3" + type: DT_RESOURCE + } + input_arg { + name: "unknown_4" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "step_type" + input: "reward" + input: "discount" + input: "callee_basic_block_count" + input: "callee_conditionally_executed_blocks" + input: "callee_users" + input: "caller_basic_block_count" + input: "caller_conditionally_executed_blocks" + input: "caller_users" + input: "callsite_height" + input: "cost_estimate" + input: "edge_count" + input: "inlining_default" + input: "node_count" + input: "nr_ctant_params" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + input: "unknown_3" + input: "unknown_4" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_FLOAT + type: DT_FLOAT + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 15 + i: 16 + i: 17 + i: 18 + i: 19 + i: 20 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_polymorphic_action_fn_4618978" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "step_type" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "reward" + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "discount" + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_basic_block_count" + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_conditionally_executed_blocks" + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_users" + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_basic_block_count" + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_conditionally_executed_blocks" + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_users" + } + } + } + } + arg_attr { + key: 9 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callsite_height" + } + } + } + } + arg_attr { + key: 10 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "cost_estimate" + } + } + } + } + arg_attr { + key: 11 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "edge_count" + } + } + } + } + arg_attr { + key: 12 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inlining_default" + } + } + } + } + arg_attr { + key: 13 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "node_count" + } + } + } + } + arg_attr { + key: 14 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "nr_ctant_params" + } + } + } + } + arg_attr { + key: 15 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 16 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 17 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 18 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 19 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 20 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_polymorphic_action_fn_4619080" + input_arg { + name: "time_step_step_type" + type: DT_INT32 + } + input_arg { + name: "time_step_reward" + type: DT_FLOAT + } + input_arg { + name: "time_step_discount" + type: DT_FLOAT + } + input_arg { + name: "time_step_observation_callee_basic_block_count" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_callee_conditionally_executed_blocks" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_callee_users" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_caller_basic_block_count" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_caller_conditionally_executed_blocks" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_caller_users" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_callsite_height" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_cost_estimate" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_edge_count" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_inlining_default" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_node_count" + type: DT_INT64 + } + input_arg { + name: "time_step_observation_nr_ctant_params" + type: DT_INT64 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + input_arg { + name: "unknown_3" + type: DT_RESOURCE + } + input_arg { + name: "unknown_4" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "time_step_step_type" + input: "time_step_reward" + input: "time_step_discount" + input: "time_step_observation_callee_basic_block_count" + input: "time_step_observation_callee_conditionally_executed_blocks" + input: "time_step_observation_callee_users" + input: "time_step_observation_caller_basic_block_count" + input: "time_step_observation_caller_conditionally_executed_blocks" + input: "time_step_observation_caller_users" + input: "time_step_observation_callsite_height" + input: "time_step_observation_cost_estimate" + input: "time_step_observation_edge_count" + input: "time_step_observation_inlining_default" + input: "time_step_observation_node_count" + input: "time_step_observation_nr_ctant_params" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + input: "unknown_3" + input: "unknown_4" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_FLOAT + type: DT_FLOAT + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 15 + i: 16 + i: 17 + i: 18 + i: 19 + i: 20 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_action_931" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/step_type" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/reward" + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/discount" + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/callee_basic_block_count" + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/callee_conditionally_executed_blocks" + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/callee_users" + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/caller_basic_block_count" + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/caller_conditionally_executed_blocks" + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/caller_users" + } + } + } + } + arg_attr { + key: 9 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/callsite_height" + } + } + } + } + arg_attr { + key: 10 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/cost_estimate" + } + } + } + } + arg_attr { + key: 11 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/edge_count" + } + } + } + } + arg_attr { + key: 12 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/inlining_default" + } + } + } + } + arg_attr { + key: 13 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/node_count" + } + } + } + } + arg_attr { + key: 14 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step/observation/nr_ctant_params" + } + } + } + } + arg_attr { + key: 15 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 16 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 17 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 18 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 19 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 20 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_function_with_signature_4619040" + input_arg { + name: "unknown" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "unknown" + attr { + key: "Tin" + value { + list { + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 0 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference__728" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_polymorphic_action_fn_4618978" + input_arg { + name: "time_step" + type: DT_INT32 + } + input_arg { + name: "time_step_1" + type: DT_FLOAT + } + input_arg { + name: "time_step_2" + type: DT_FLOAT + } + input_arg { + name: "time_step_3" + type: DT_INT64 + } + input_arg { + name: "time_step_4" + type: DT_INT64 + } + input_arg { + name: "time_step_5" + type: DT_INT64 + } + input_arg { + name: "time_step_6" + type: DT_INT64 + } + input_arg { + name: "time_step_7" + type: DT_INT64 + } + input_arg { + name: "time_step_8" + type: DT_INT64 + } + input_arg { + name: "time_step_9" + type: DT_INT64 + } + input_arg { + name: "time_step_10" + type: DT_INT64 + } + input_arg { + name: "time_step_11" + type: DT_INT64 + } + input_arg { + name: "time_step_12" + type: DT_INT64 + } + input_arg { + name: "time_step_13" + type: DT_INT64 + } + input_arg { + name: "time_step_14" + type: DT_INT64 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + input_arg { + name: "unknown_3" + type: DT_RESOURCE + } + input_arg { + name: "unknown_4" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "time_step" + input: "time_step_1" + input: "time_step_2" + input: "time_step_3" + input: "time_step_4" + input: "time_step_5" + input: "time_step_6" + input: "time_step_7" + input: "time_step_8" + input: "time_step_9" + input: "time_step_10" + input: "time_step_11" + input: "time_step_12" + input: "time_step_13" + input: "time_step_14" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + input: "unknown_3" + input: "unknown_4" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_FLOAT + type: DT_FLOAT + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 15 + i: 16 + i: 17 + i: 18 + i: 19 + i: 20 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_action_931" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 9 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 10 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 11 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 12 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 13 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 14 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "time_step" + } + } + } + } + arg_attr { + key: 15 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 16 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 17 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 18 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 19 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 20 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_polymorphic_action_fn_946" + input_arg { + name: "step_type" + type: DT_INT32 + } + input_arg { + name: "reward" + type: DT_FLOAT + } + input_arg { + name: "discount" + type: DT_FLOAT + } + input_arg { + name: "callee_basic_block_count" + type: DT_INT64 + } + input_arg { + name: "callee_conditionally_executed_blocks" + type: DT_INT64 + } + input_arg { + name: "callee_users" + type: DT_INT64 + } + input_arg { + name: "caller_basic_block_count" + type: DT_INT64 + } + input_arg { + name: "caller_conditionally_executed_blocks" + type: DT_INT64 + } + input_arg { + name: "caller_users" + type: DT_INT64 + } + input_arg { + name: "callsite_height" + type: DT_INT64 + } + input_arg { + name: "cost_estimate" + type: DT_INT64 + } + input_arg { + name: "edge_count" + type: DT_INT64 + } + input_arg { + name: "inlining_default" + type: DT_INT64 + } + input_arg { + name: "node_count" + type: DT_INT64 + } + input_arg { + name: "nr_ctant_params" + type: DT_INT64 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + input_arg { + name: "unknown_3" + type: DT_RESOURCE + } + input_arg { + name: "unknown_4" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "step_type" + input: "reward" + input: "discount" + input: "callee_basic_block_count" + input: "callee_conditionally_executed_blocks" + input: "callee_users" + input: "caller_basic_block_count" + input: "caller_conditionally_executed_blocks" + input: "caller_users" + input: "callsite_height" + input: "cost_estimate" + input: "edge_count" + input: "inlining_default" + input: "node_count" + input: "nr_ctant_params" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + input: "unknown_3" + input: "unknown_4" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_FLOAT + type: DT_FLOAT + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_INT64 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_INT64 + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 15 + i: 16 + i: 17 + i: 18 + i: 19 + i: 20 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0012\005*\0010J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_action_931" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "step_type" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "reward" + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "discount" + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_basic_block_count" + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_conditionally_executed_blocks" + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callee_users" + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_basic_block_count" + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_conditionally_executed_blocks" + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "caller_users" + } + } + } + } + arg_attr { + key: 9 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "callsite_height" + } + } + } + } + arg_attr { + key: 10 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "cost_estimate" + } + } + } + } + arg_attr { + key: 11 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "edge_count" + } + } + } + } + arg_attr { + key: 12 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inlining_default" + } + } + } + } + arg_attr { + key: 13 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "node_count" + } + } + } + } + arg_attr { + key: 14 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "nr_ctant_params" + } + } + } + } + arg_attr { + key: 15 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 16 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 17 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 18 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 19 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 20 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference__traced_restore_4619176" + input_arg { + name: "file_prefix" + type: DT_STRING + } + input_arg { + name: "assignvariableop_train_step" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_1_qnetwork_encodingnetwork_dense_kernel" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_2_qnetwork_encodingnetwork_dense_bias" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_3_qnetwork_encodingnetwork_dense_1_kernel" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_4_qnetwork_encodingnetwork_dense_1_bias" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_5_qnetwork_dense_2_kernel" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_6_qnetwork_dense_2_bias" + type: DT_RESOURCE + } + output_arg { + name: "identity_8" + type: DT_STRING + } + is_stateful: true + control_output: "AssignVariableOp" + control_output: "AssignVariableOp_1" + control_output: "AssignVariableOp_2" + control_output: "AssignVariableOp_3" + control_output: "AssignVariableOp_4" + control_output: "AssignVariableOp_5" + control_output: "AssignVariableOp_6" + control_output: "RestoreV2" + control_output: "RestoreV2_1" + } + node_def { + name: "RestoreV2/tensor_names" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 7 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 7 + } + } + string_val: "train_step/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/0/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/1/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/2/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/3/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/4/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "model_variables/5/.ATTRIBUTES/VARIABLE_VALUE" + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2/tensor_names" + } + } + node_def { + name: "RestoreV2/shape_and_slices" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 7 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 7 + } + } + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2/shape_and_slices" + } + } + node_def { + name: "RestoreV2" + op: "RestoreV2" + input: "file_prefix" + input: "RestoreV2/tensor_names:output:0" + input: "RestoreV2/shape_and_slices:output:0" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + attr { + key: "dtypes" + value { + list { + type: DT_INT64 + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "RestoreV2:tensors:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + node_def { + name: "AssignVariableOp" + op: "AssignVariableOp" + input: "assignvariableop_train_step" + input: "Identity:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp" + } + } + node_def { + name: "Identity_1" + op: "Identity" + input: "RestoreV2:tensors:1" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_1" + } + } + node_def { + name: "AssignVariableOp_1" + op: "AssignVariableOp" + input: "assignvariableop_1_qnetwork_encodingnetwork_dense_kernel" + input: "Identity_1:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_1" + } + } + node_def { + name: "Identity_2" + op: "Identity" + input: "RestoreV2:tensors:2" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_2" + } + } + node_def { + name: "AssignVariableOp_2" + op: "AssignVariableOp" + input: "assignvariableop_2_qnetwork_encodingnetwork_dense_bias" + input: "Identity_2:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_2" + } + } + node_def { + name: "Identity_3" + op: "Identity" + input: "RestoreV2:tensors:3" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_3" + } + } + node_def { + name: "AssignVariableOp_3" + op: "AssignVariableOp" + input: "assignvariableop_3_qnetwork_encodingnetwork_dense_1_kernel" + input: "Identity_3:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_3" + } + } + node_def { + name: "Identity_4" + op: "Identity" + input: "RestoreV2:tensors:4" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_4" + } + } + node_def { + name: "AssignVariableOp_4" + op: "AssignVariableOp" + input: "assignvariableop_4_qnetwork_encodingnetwork_dense_1_bias" + input: "Identity_4:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_4" + } + } + node_def { + name: "Identity_5" + op: "Identity" + input: "RestoreV2:tensors:5" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_5" + } + } + node_def { + name: "AssignVariableOp_5" + op: "AssignVariableOp" + input: "assignvariableop_5_qnetwork_dense_2_kernel" + input: "Identity_5:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_5" + } + } + node_def { + name: "Identity_6" + op: "Identity" + input: "RestoreV2:tensors:6" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_6" + } + } + node_def { + name: "AssignVariableOp_6" + op: "AssignVariableOp" + input: "assignvariableop_6_qnetwork_dense_2_bias" + input: "Identity_6:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_6" + } + } + node_def { + name: "RestoreV2_1/tensor_names" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 1 + } + } + string_val: "_CHECKPOINTABLE_OBJECT_GRAPH" + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2_1/tensor_names" + } + } + node_def { + name: "RestoreV2_1/shape_and_slices" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 1 + } + } + string_val: "" + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2_1/shape_and_slices" + } + } + node_def { + name: "RestoreV2_1" + op: "RestoreV2" + input: "file_prefix" + input: "RestoreV2_1/tensor_names:output:0" + input: "RestoreV2_1/shape_and_slices:output:0" + input: "^RestoreV2" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + attr { + key: "dtypes" + value { + list { + type: DT_STRING + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2_1" + } + } + node_def { + name: "NoOp" + op: "NoOp" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + experimental_debug_info { + original_node_names: "NoOp" + } + } + node_def { + name: "Identity_7" + op: "Identity" + input: "file_prefix" + input: "^AssignVariableOp" + input: "^AssignVariableOp_1" + input: "^AssignVariableOp_2" + input: "^AssignVariableOp_3" + input: "^AssignVariableOp_4" + input: "^AssignVariableOp_5" + input: "^AssignVariableOp_6" + input: "^NoOp" + device: "/device:CPU:0" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_7" + } + } + node_def { + name: "Identity_8" + op: "Identity" + input: "Identity_7:output:0" + input: "^AssignVariableOp" + input: "^AssignVariableOp_1" + input: "^AssignVariableOp_2" + input: "^AssignVariableOp_3" + input: "^AssignVariableOp_4" + input: "^AssignVariableOp_5" + input: "^AssignVariableOp_6" + input: "^RestoreV2" + input: "^RestoreV2_1" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_8" + } + } + ret { + key: "identity_8" + value: "Identity_8:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "AssignVariableOp" + value: "AssignVariableOp" + } + control_ret { + key: "AssignVariableOp_1" + value: "AssignVariableOp_1" + } + control_ret { + key: "AssignVariableOp_2" + value: "AssignVariableOp_2" + } + control_ret { + key: "AssignVariableOp_3" + value: "AssignVariableOp_3" + } + control_ret { + key: "AssignVariableOp_4" + value: "AssignVariableOp_4" + } + control_ret { + key: "AssignVariableOp_5" + value: "AssignVariableOp_5" + } + control_ret { + key: "AssignVariableOp_6" + value: "AssignVariableOp_6" + } + control_ret { + key: "RestoreV2" + value: "RestoreV2" + } + control_ret { + key: "RestoreV2_1" + value: "RestoreV2_1" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "file_prefix" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference__728" + input_arg { + name: "readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_INT64 + } + is_stateful: true + } + node_def { + name: "ReadVariableOp" + op: "ReadVariableOp" + input: "readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT64 + } + } + experimental_debug_info { + original_node_names: "ReadVariableOp" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_INT64 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + } + versions { + producer: 357 + min_consumer: 12 + } + } + saver_def { + filename_tensor_name: "saver_filename:0" + save_tensor_name: "StatefulPartitionedCall_2:0" + restore_op_name: "StatefulPartitionedCall_3" + version: V2 + } + collection_def { + key: "saved_model_main_op" + value { + node_list { + value: "NoOp" + } + } + } + signature_def { + key: "__saved_model_init_op" + value { + outputs { + key: "__saved_model_init_op" + value { + name: "NoOp" + tensor_shape { + unknown_rank: true + } + } + } + } + } + signature_def { + key: "action" + value { + inputs { + key: "callee_basic_block_count" + value { + name: "action_callee_basic_block_count:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "callee_conditionally_executed_blocks" + value { + name: "action_callee_conditionally_executed_blocks:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "callee_users" + value { + name: "action_callee_users:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "caller_basic_block_count" + value { + name: "action_caller_basic_block_count:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "caller_conditionally_executed_blocks" + value { + name: "action_caller_conditionally_executed_blocks:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "caller_users" + value { + name: "action_caller_users:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "callsite_height" + value { + name: "action_callsite_height:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "cost_estimate" + value { + name: "action_cost_estimate:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "discount" + value { + name: "action_discount:0" + dtype: DT_FLOAT + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "edge_count" + value { + name: "action_edge_count:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "inlining_default" + value { + name: "action_inlining_default:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "node_count" + value { + name: "action_node_count:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "nr_ctant_params" + value { + name: "action_nr_ctant_params:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "reward" + value { + name: "action_reward:0" + dtype: DT_FLOAT + tensor_shape { + dim { + size: 1 + } + } + } + } + inputs { + key: "step_type" + value { + name: "action_step_type:0" + dtype: DT_INT32 + tensor_shape { + dim { + size: 1 + } + } + } + } + outputs { + key: "inlining_decision" + value { + name: "StatefulPartitionedCall:0" + dtype: DT_INT64 + tensor_shape { + dim { + size: 1 + } + } + } + } + method_name: "tensorflow/serving/predict" + } + } + signature_def { + key: "get_initial_state" + value { + method_name: "tensorflow/serving/predict" + } + } + signature_def { + key: "get_train_step" + value { + outputs { + key: "int64" + value { + name: "StatefulPartitionedCall_1:0" + dtype: DT_INT64 + tensor_shape { + } + } + } + method_name: "tensorflow/serving/predict" + } + } + object_graph_def { + nodes { + children { + node_id: 1 + local_name: "_time_step_spec" + } + children { + node_id: 2 + local_name: "_trajectory_spec" + } + children { + node_id: 3 + local_name: "_wrapped_policy" + } + children { + node_id: 4 + local_name: "train_step" + } + children { + node_id: 5 + local_name: "model_variables" + } + children { + node_id: 6 + local_name: "signatures" + } + children { + node_id: 210 + local_name: "action" + } + children { + node_id: 211 + local_name: "get_initial_state" + } + children { + node_id: 212 + local_name: "get_train_step" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 7 + local_name: "observation" + } + children { + node_id: 7 + local_name: "3" + } + user_object { + identifier: "trackable_tuple_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 7 + local_name: "observation" + } + children { + node_id: 7 + local_name: "1" + } + user_object { + identifier: "trackable_tuple_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 8 + local_name: "_q_network" + } + children { + node_id: 1 + local_name: "_time_step_spec" + } + children { + node_id: 9 + local_name: "_trajectory_spec" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + variable { + dtype: DT_INT64 + shape { + } + name: "train_step" + } + } + nodes { + children { + node_id: 10 + local_name: "0" + } + children { + node_id: 11 + local_name: "1" + } + children { + node_id: 12 + local_name: "2" + } + children { + node_id: 13 + local_name: "3" + } + children { + node_id: 14 + local_name: "4" + } + children { + node_id: 15 + local_name: "5" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 213 + local_name: "action" + } + children { + node_id: 214 + local_name: "get_initial_state" + } + children { + node_id: 215 + local_name: "get_train_step" + } + user_object { + identifier: "signature_map" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 16 + local_name: "_input_tensor_spec" + } + children { + node_id: 17 + local_name: "_encoder" + } + children { + node_id: 18 + local_name: "_q_value_layer" + } + children { + node_id: 19 + local_name: "variables" + } + children { + node_id: 20 + local_name: "regularization_losses" + } + children { + node_id: 21 + local_name: "trainable_variables" + } + children { + node_id: 22 + local_name: "keras_api" + } + children { + node_id: 216 + local_name: "__call__" + } + children { + node_id: 217 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_network" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"QNetwork\", \"name\": \"QNetwork\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"config\": {\"layer was saved without config\": true}, \"is_graph_network\": false}" + } + } + nodes { + children { + node_id: 7 + local_name: "observation" + } + children { + node_id: 7 + local_name: "1" + } + user_object { + identifier: "trackable_tuple_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 34 + } + dim { + size: 100 + } + } + trainable: true + name: "QNetwork/EncodingNetwork/dense/kernel" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 100 + } + } + trainable: true + name: "QNetwork/EncodingNetwork/dense/bias" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 100 + } + dim { + size: 40 + } + } + trainable: true + name: "QNetwork/EncodingNetwork/dense_1/kernel" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 40 + } + } + trainable: true + name: "QNetwork/EncodingNetwork/dense_1/bias" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 40 + } + dim { + size: 2 + } + } + trainable: true + name: "QNetwork/dense_2/kernel" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 2 + } + } + trainable: true + name: "QNetwork/dense_2/bias" + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 23 + local_name: "_input_tensor_spec" + } + children { + node_id: 24 + local_name: "_preprocessing_nest" + } + children { + node_id: 25 + local_name: "_flat_preprocessing_layers" + } + children { + node_id: 26 + local_name: "_preprocessing_combiner" + } + children { + node_id: 27 + local_name: "_postprocessing_layers" + } + children { + node_id: 28 + local_name: "variables" + } + children { + node_id: 29 + local_name: "regularization_losses" + } + children { + node_id: 30 + local_name: "trainable_variables" + } + children { + node_id: 31 + local_name: "keras_api" + } + children { + node_id: 218 + local_name: "__call__" + } + children { + node_id: 219 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_network" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"EncodingNetwork\", \"name\": \"EncodingNetwork\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"config\": {\"layer was saved without config\": true}, \"is_graph_network\": false}" + } + } + nodes { + children { + node_id: 14 + local_name: "kernel" + } + children { + node_id: 15 + local_name: "bias" + } + children { + node_id: 32 + local_name: "variables" + } + children { + node_id: 33 + local_name: "regularization_losses" + } + children { + node_id: 34 + local_name: "trainable_variables" + } + children { + node_id: 35 + local_name: "keras_api" + } + children { + node_id: 220 + local_name: "__call__" + } + children { + node_id: 221 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Dense\", \"name\": \"dense_2\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense_2\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 2, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"RandomUniform\", \"config\": {\"minval\": -0.03, \"maxval\": 0.03, \"seed\": null, \"dtype\": \"float32\"}}, \"bias_initializer\": {\"class_name\": \"Constant\", \"config\": {\"value\": -0.2, \"dtype\": \"float32\"}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 40}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [0, 40]}}" + } + } + nodes { + children { + node_id: 10 + local_name: "0" + } + children { + node_id: 11 + local_name: "1" + } + children { + node_id: 12 + local_name: "2" + } + children { + node_id: 13 + local_name: "3" + } + children { + node_id: 14 + local_name: "4" + } + children { + node_id: 15 + local_name: "5" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 10 + local_name: "0" + } + children { + node_id: 11 + local_name: "1" + } + children { + node_id: 12 + local_name: "2" + } + children { + node_id: 13 + local_name: "3" + } + children { + node_id: 14 + local_name: "4" + } + children { + node_id: 15 + local_name: "5" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 36 + local_name: "layer_metrics" + } + children { + node_id: 19 + local_name: "variables" + } + children { + node_id: 37 + local_name: "layer_regularization_losses" + } + children { + node_id: 38 + local_name: "metrics" + } + children { + node_id: 39 + local_name: "layers" + } + children { + node_id: 20 + local_name: "regularization_losses" + } + children { + node_id: 40 + local_name: "non_trainable_variables" + } + children { + node_id: 21 + local_name: "trainable_variables" + } + children { + node_id: 216 + local_name: "__call__" + } + children { + node_id: 217 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 217 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 41 + local_name: "0" + } + children { + node_id: 42 + local_name: "1" + } + children { + node_id: 43 + local_name: "2" + } + children { + node_id: 44 + local_name: "3" + } + children { + node_id: 45 + local_name: "4" + } + children { + node_id: 46 + local_name: "5" + } + children { + node_id: 47 + local_name: "6" + } + children { + node_id: 48 + local_name: "7" + } + children { + node_id: 49 + local_name: "8" + } + children { + node_id: 50 + local_name: "9" + } + children { + node_id: 51 + local_name: "10" + } + children { + node_id: 52 + local_name: "11" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 53 + local_name: "variables" + } + children { + node_id: 54 + local_name: "regularization_losses" + } + children { + node_id: 55 + local_name: "trainable_variables" + } + children { + node_id: 56 + local_name: "keras_api" + } + children { + node_id: 222 + local_name: "__call__" + } + children { + node_id: 223 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Concatenate\", \"name\": \"concatenate\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"concatenate\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}, \"build_input_shape\": [{\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 1]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}, {\"class_name\": \"TensorShape\", \"items\": [0, 3]}]}" + } + } + nodes { + children { + node_id: 57 + local_name: "0" + } + children { + node_id: 58 + local_name: "1" + } + children { + node_id: 59 + local_name: "2" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 10 + local_name: "0" + } + children { + node_id: 11 + local_name: "1" + } + children { + node_id: 12 + local_name: "2" + } + children { + node_id: 13 + local_name: "3" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 10 + local_name: "0" + } + children { + node_id: 11 + local_name: "1" + } + children { + node_id: 12 + local_name: "2" + } + children { + node_id: 13 + local_name: "3" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 60 + local_name: "layer_metrics" + } + children { + node_id: 28 + local_name: "variables" + } + children { + node_id: 61 + local_name: "layer_regularization_losses" + } + children { + node_id: 62 + local_name: "metrics" + } + children { + node_id: 63 + local_name: "layers" + } + children { + node_id: 29 + local_name: "regularization_losses" + } + children { + node_id: 64 + local_name: "non_trainable_variables" + } + children { + node_id: 30 + local_name: "trainable_variables" + } + children { + node_id: 218 + local_name: "__call__" + } + children { + node_id: 219 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 219 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 14 + local_name: "0" + } + children { + node_id: 15 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 14 + local_name: "0" + } + children { + node_id: 15 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 65 + local_name: "layer_metrics" + } + children { + node_id: 32 + local_name: "variables" + } + children { + node_id: 66 + local_name: "layer_regularization_losses" + } + children { + node_id: 67 + local_name: "metrics" + } + children { + node_id: 68 + local_name: "layers" + } + children { + node_id: 33 + local_name: "regularization_losses" + } + children { + node_id: 69 + local_name: "non_trainable_variables" + } + children { + node_id: 34 + local_name: "trainable_variables" + } + children { + node_id: 220 + local_name: "__call__" + } + children { + node_id: 221 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 221 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 17 + local_name: "0" + } + children { + node_id: 18 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 70 + local_name: "variables" + } + children { + node_id: 71 + local_name: "regularization_losses" + } + children { + node_id: 72 + local_name: "trainable_variables" + } + children { + node_id: 73 + local_name: "keras_api" + } + children { + node_id: 224 + local_name: "__call__" + } + children { + node_id: 225 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 9.0, 9.0, 9.0, 9.0, 10.0, 10.0, 11.0, 12.0, 13.0, 14.0, 14.0, 14.0, 16.0, 17.0, 19.0, 23.0, 27.0, 39.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 74 + local_name: "variables" + } + children { + node_id: 75 + local_name: "regularization_losses" + } + children { + node_id: 76 + local_name: "trainable_variables" + } + children { + node_id: 77 + local_name: "keras_api" + } + children { + node_id: 226 + local_name: "__call__" + } + children { + node_id: 227 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_1\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_1\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 8.0, 8.0, 8.0, 8.0, 9.0, 10.0, 10.0, 10.0, 12.0, 12.0, 12.0, 14.0, 14.0, 18.0, 20.0, 23.0, 30.0, 41.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 78 + local_name: "variables" + } + children { + node_id: 79 + local_name: "regularization_losses" + } + children { + node_id: 80 + local_name: "trainable_variables" + } + children { + node_id: 81 + local_name: "keras_api" + } + children { + node_id: 228 + local_name: "__call__" + } + children { + node_id: 229 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_2\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_2\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 18.0, 18.0, 18.0, 18.0, 18.0, 19.0, 19.0, 19.0, 19.0, 19.0, 20.0, 20.0, 20.0, 20.0, 20.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 22.0, 22.0, 22.0, 22.0, 23.0, 23.0, 23.0, 24.0, 24.0, 24.0, 25.0, 25.0, 25.0, 25.0, 25.0, 25.0, 26.0, 26.0, 26.0, 27.0, 27.0, 27.0, 27.0, 28.0, 28.0, 29.0, 29.0, 29.0, 29.0, 30.0, 30.0, 31.0, 31.0, 31.0, 31.0, 32.0, 32.0, 33.0, 33.0, 33.0, 34.0, 34.0, 34.0, 34.0, 35.0, 35.0, 36.0, 36.0, 37.0, 37.0, 37.0, 38.0, 38.0, 39.0, 39.0, 40.0, 40.0, 41.0, 41.0, 41.0, 42.0, 43.0, 43.0, 44.0, 44.0, 45.0, 45.0, 46.0, 46.0, 46.0, 47.0, 47.0, 48.0, 49.0, 49.0, 50.0, 50.0, 51.0, 52.0, 53.0, 53.0, 54.0, 55.0, 56.0, 57.0, 57.0, 58.0, 59.0, 60.0, 61.0, 61.0, 63.0, 63.0, 64.0, 65.0, 66.0, 67.0, 67.0, 69.0, 70.0, 71.0, 72.0, 73.0, 74.0, 75.0, 77.0, 78.0, 79.0, 80.0, 81.0, 82.0, 83.0, 85.0, 86.0, 88.0, 89.0, 91.0, 92.0, 94.0, 96.0, 97.0, 99.0, 100.0, 101.0, 103.0, 105.0, 107.0, 109.0, 111.0, 113.0, 115.0, 118.0, 121.0, 123.0, 126.0, 128.0, 130.0, 133.0, 135.0, 137.0, 140.0, 143.0, 146.0, 148.0, 151.0, 154.0, 157.0, 161.0, 163.0, 166.0, 169.0, 173.0, 178.0, 183.0, 189.0, 193.0, 197.0, 202.0, 208.0, 213.0, 218.0, 223.0, 228.0, 233.0, 239.0, 245.0, 250.0, 257.0, 262.0, 269.0, 277.0, 284.0, 292.0, 300.0, 308.0, 319.0, 329.0, 340.0, 349.0, 359.0, 371.0, 382.0, 394.0, 410.0, 423.0, 435.0, 445.0, 462.0, 480.0, 492.0, 506.0, 519.0, 536.0, 557.0, 577.0, 598.0, 622.0, 655.0, 679.0, 707.0, 733.0, 751.0, 787.0, 814.0, 847.0, 897.0, 934.0, 997.0, 1062.0, 1111.0, 1181.0, 1275.0, 1385.0, 1465.0, 1603.0, 1769.0, 2057.0, 2257.0, 2803.0, 3468.0, 4417.0, 6538.0, 16126.0, 23446.0, 33536.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 82 + local_name: "variables" + } + children { + node_id: 83 + local_name: "regularization_losses" + } + children { + node_id: 84 + local_name: "trainable_variables" + } + children { + node_id: 85 + local_name: "keras_api" + } + children { + node_id: 230 + local_name: "__call__" + } + children { + node_id: 231 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_3\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_3\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 20.0, 20.0, 20.0, 20.0, 20.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 23.0, 23.0, 23.0, 24.0, 24.0, 24.0, 24.0, 24.0, 24.0, 25.0, 25.0, 25.0, 25.0, 25.0, 26.0, 26.0, 26.0, 26.0, 27.0, 27.0, 27.0, 27.0, 27.0, 28.0, 28.0, 28.0, 29.0, 29.0, 29.0, 29.0, 30.0, 30.0, 30.0, 31.0, 31.0, 31.0, 32.0, 32.0, 32.0, 33.0, 33.0, 33.0, 34.0, 34.0, 34.0, 34.0, 35.0, 35.0, 35.0, 36.0, 36.0, 36.0, 37.0, 37.0, 37.0, 38.0, 38.0, 38.0, 38.0, 39.0, 39.0, 40.0, 40.0, 41.0, 41.0, 42.0, 43.0, 43.0, 44.0, 45.0, 45.0, 46.0, 47.0, 47.0, 48.0, 49.0, 49.0, 50.0, 50.0, 52.0, 52.0, 53.0, 54.0, 55.0, 55.0, 57.0, 58.0, 59.0, 60.0, 62.0, 64.0, 65.0, 66.0, 68.0, 70.0, 70.0, 70.0, 70.0, 70.0, 71.0, 73.0, 75.0, 76.0, 78.0, 81.0, 84.0, 86.0, 90.0, 94.0, 98.0, 101.0, 106.0, 111.0, 117.0, 123.0, 130.0, 138.0, 146.0, 157.0, 163.0, 176.0, 187.0, 198.0, 214.0, 227.0, 252.0, 280.0, 327.0, 395.0, 506.0, 671.0, 1025.0, 1971.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 86 + local_name: "variables" + } + children { + node_id: 87 + local_name: "regularization_losses" + } + children { + node_id: 88 + local_name: "trainable_variables" + } + children { + node_id: 89 + local_name: "keras_api" + } + children { + node_id: 232 + local_name: "__call__" + } + children { + node_id: 233 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_4\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_4\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 11.0, 11.0, 11.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 13.0, 13.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 19.0, 19.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 21.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 24.0, 24.0, 24.0, 24.0, 24.0, 24.0, 24.0, 24.0, 25.0, 26.0, 26.0, 26.0, 26.0, 26.0, 26.0, 26.0, 26.0, 26.0, 26.0, 27.0, 28.0, 28.0, 28.0, 28.0, 28.0, 29.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 31.0, 32.0, 32.0, 32.0, 32.0, 32.0, 34.0, 34.0, 34.0, 34.0, 34.0, 34.0, 35.0, 36.0, 36.0, 36.0, 37.0, 38.0, 38.0, 38.0, 39.0, 40.0, 40.0, 41.0, 42.0, 42.0, 43.0, 44.0, 44.0, 46.0, 46.0, 47.0, 48.0, 48.0, 50.0, 50.0, 52.0, 52.0, 54.0, 55.0, 55.0, 56.0, 57.0, 58.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 62.0, 62.0, 64.0, 65.0, 66.0, 68.0, 70.0, 72.0, 74.0, 77.0, 80.0, 82.0, 86.0, 89.0, 92.0, 96.0, 99.0, 104.0, 108.0, 114.0, 119.0, 125.0, 131.0, 139.0, 146.0, 157.0, 167.0, 176.0, 188.0, 198.0, 215.0, 236.0, 262.0, 306.0, 376.0, 462.0, 596.0, 942.0, 1428.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 90 + local_name: "variables" + } + children { + node_id: 91 + local_name: "regularization_losses" + } + children { + node_id: 92 + local_name: "trainable_variables" + } + children { + node_id: 93 + local_name: "keras_api" + } + children { + node_id: 234 + local_name: "__call__" + } + children { + node_id: 235 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_5\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_5\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 9.0, 9.0, 9.0, 9.0, 9.0, 10.0, 10.0, 11.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 18.0, 20.0, 23.0, 29.0, 38.0, 60.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 94 + local_name: "variables" + } + children { + node_id: 95 + local_name: "regularization_losses" + } + children { + node_id: 96 + local_name: "trainable_variables" + } + children { + node_id: 97 + local_name: "keras_api" + } + children { + node_id: 236 + local_name: "__call__" + } + children { + node_id: 237 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_6\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_6\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 8.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 11.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 12.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 13.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 14.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 16.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 18.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 19.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 21.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 23.0, 23.0, 23.0, 23.0, 23.0, 23.0, 23.0, 24.0, 24.0, 24.0, 24.0, 24.0, 25.0, 25.0, 25.0, 25.0, 25.0, 26.0, 26.0, 26.0, 26.0, 27.0, 27.0, 27.0, 28.0, 28.0, 28.0, 29.0, 29.0, 30.0, 30.0, 30.0, 31.0, 31.0, 32.0, 32.0, 33.0, 33.0, 34.0, 35.0, 37.0, 38.0, 40.0, 46.0, 51.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 98 + local_name: "variables" + } + children { + node_id: 99 + local_name: "regularization_losses" + } + children { + node_id: 100 + local_name: "trainable_variables" + } + children { + node_id: 101 + local_name: "keras_api" + } + children { + node_id: 238 + local_name: "__call__" + } + children { + node_id: 239 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_7\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_7\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [-15035.0, -15030.0, -15025.0, -15000.0, -14985.0, -14945.0, -14745.0, -70.0, -55.0, -55.0, -50.0, -50.0, -50.0, -45.0, -45.0, -45.0, -45.0, -45.0, -45.0, -45.0, -45.0, -45.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -40.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -35.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -30.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -25.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -20.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -15.0, -10.0, -10.0, -10.0, -10.0, -10.0, -10.0, -10.0, -10.0, -10.0, -10.0, -10.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, -5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 15.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 20.0, 25.0, 25.0, 25.0, 25.0, 25.0, 25.0, 25.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 35.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 40.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 45.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 50.0, 55.0, 55.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 60.0, 65.0, 65.0, 65.0, 65.0, 65.0, 65.0, 65.0, 65.0, 65.0, 65.0, 65.0, 65.0, 70.0, 70.0, 70.0, 70.0, 70.0, 70.0, 70.0, 75.0, 75.0, 80.0, 80.0, 80.0, 85.0, 85.0, 85.0, 90.0, 90.0, 90.0, 90.0, 95.0, 95.0, 100.0, 100.0, 105.0, 110.0, 115.0, 120.0, 125.0, 125.0, 130.0, 140.0, 140.0, 145.0, 150.0, 155.0, 160.0, 160.0, 165.0, 170.0, 175.0, 180.0, 190.0, 200.0, 210.0, 215.0, 220.0, 220.0, 230.0, 235.0, 245.0, 250.0, 260.0, 275.0, 290.0, 305.0, 325.0, 350.0, 370.0, 390.0, 425.0, 460.0, 500.0, 560.0, 650.0, 790.0, 1025.0, 1600.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 102 + local_name: "variables" + } + children { + node_id: 103 + local_name: "regularization_losses" + } + children { + node_id: 104 + local_name: "trainable_variables" + } + children { + node_id: 105 + local_name: "keras_api" + } + children { + node_id: 240 + local_name: "__call__" + } + children { + node_id: 241 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_8\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_8\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [18.0, 29.0, 39.0, 48.0, 57.0, 64.0, 70.0, 76.0, 82.0, 87.0, 92.0, 97.0, 101.0, 105.0, 109.0, 113.0, 116.0, 120.0, 123.0, 127.0, 130.0, 134.0, 137.0, 140.0, 143.0, 146.0, 149.0, 152.0, 156.0, 159.0, 162.0, 165.0, 168.0, 171.0, 174.0, 177.0, 180.0, 183.0, 186.0, 188.0, 191.0, 194.0, 197.0, 200.0, 203.0, 205.0, 208.0, 211.0, 214.0, 217.0, 219.0, 222.0, 225.0, 228.0, 231.0, 233.0, 236.0, 239.0, 242.0, 244.0, 247.0, 250.0, 253.0, 255.0, 258.0, 261.0, 264.0, 266.0, 269.0, 272.0, 275.0, 278.0, 280.0, 283.0, 286.0, 289.0, 292.0, 294.0, 297.0, 300.0, 303.0, 305.0, 308.0, 311.0, 314.0, 317.0, 319.0, 322.0, 325.0, 327.0, 330.0, 333.0, 336.0, 339.0, 341.0, 344.0, 347.0, 350.0, 353.0, 355.0, 358.0, 361.0, 364.0, 367.0, 370.0, 373.0, 375.0, 378.0, 381.0, 384.0, 387.0, 390.0, 393.0, 396.0, 399.0, 401.0, 404.0, 407.0, 410.0, 413.0, 416.0, 419.0, 422.0, 425.0, 428.0, 431.0, 434.0, 437.0, 440.0, 443.0, 446.0, 449.0, 452.0, 455.0, 458.0, 461.0, 464.0, 467.0, 470.0, 473.0, 476.0, 479.0, 483.0, 486.0, 489.0, 492.0, 495.0, 498.0, 501.0, 504.0, 507.0, 511.0, 514.0, 517.0, 520.0, 523.0, 526.0, 530.0, 533.0, 536.0, 539.0, 542.0, 545.0, 549.0, 552.0, 555.0, 558.0, 562.0, 565.0, 569.0, 572.0, 575.0, 579.0, 582.0, 585.0, 589.0, 592.0, 595.0, 599.0, 602.0, 605.0, 609.0, 612.0, 616.0, 620.0, 623.0, 626.0, 630.0, 634.0, 637.0, 641.0, 644.0, 648.0, 651.0, 655.0, 658.0, 662.0, 665.0, 669.0, 672.0, 676.0, 680.0, 683.0, 687.0, 691.0, 694.0, 698.0, 702.0, 705.0, 709.0, 712.0, 716.0, 720.0, 724.0, 727.0, 731.0, 735.0, 739.0, 742.0, 746.0, 750.0, 754.0, 758.0, 761.0, 765.0, 769.0, 773.0, 777.0, 780.0, 784.0, 788.0, 792.0, 796.0, 800.0, 804.0, 808.0, 812.0, 816.0, 820.0, 823.0, 828.0, 832.0, 836.0, 840.0, 844.0, 848.0, 852.0, 856.0, 860.0, 864.0, 868.0, 873.0, 877.0, 881.0, 885.0, 889.0, 893.0, 897.0, 902.0, 906.0, 910.0, 914.0, 919.0, 923.0, 927.0, 931.0, 935.0, 940.0, 944.0, 948.0, 953.0, 957.0, 962.0, 966.0, 970.0, 975.0, 979.0, 984.0, 988.0, 993.0, 997.0, 1002.0, 1006.0, 1011.0, 1015.0, 1020.0, 1024.0, 1029.0, 1034.0, 1038.0, 1043.0, 1047.0, 1052.0, 1057.0, 1062.0, 1066.0, 1071.0, 1076.0, 1081.0, 1086.0, 1090.0, 1095.0, 1100.0, 1105.0, 1110.0, 1114.0, 1119.0, 1124.0, 1129.0, 1134.0, 1139.0, 1144.0, 1149.0, 1154.0, 1159.0, 1164.0, 1169.0, 1174.0, 1179.0, 1184.0, 1189.0, 1194.0, 1199.0, 1204.0, 1209.0, 1215.0, 1220.0, 1225.0, 1230.0, 1235.0, 1241.0, 1246.0, 1251.0, 1257.0, 1262.0, 1267.0, 1273.0, 1278.0, 1284.0, 1289.0, 1294.0, 1300.0, 1305.0, 1311.0, 1316.0, 1322.0, 1327.0, 1333.0, 1338.0, 1344.0, 1350.0, 1355.0, 1361.0, 1367.0, 1372.0, 1378.0, 1383.0, 1389.0, 1395.0, 1401.0, 1407.0, 1413.0, 1418.0, 1424.0, 1430.0, 1436.0, 1442.0, 1448.0, 1454.0, 1459.0, 1465.0, 1472.0, 1477.0, 1483.0, 1489.0, 1495.0, 1501.0, 1507.0, 1514.0, 1520.0, 1526.0, 1532.0, 1538.0, 1545.0, 1551.0, 1557.0, 1564.0, 1570.0, 1576.0, 1583.0, 1589.0, 1596.0, 1602.0, 1608.0, 1615.0, 1621.0, 1628.0, 1634.0, 1641.0, 1647.0, 1654.0, 1661.0, 1667.0, 1674.0, 1681.0, 1687.0, 1694.0, 1701.0, 1708.0, 1715.0, 1722.0, 1729.0, 1735.0, 1742.0, 1749.0, 1756.0, 1763.0, 1770.0, 1777.0, 1784.0, 1791.0, 1798.0, 1806.0, 1812.0, 1820.0, 1827.0, 1835.0, 1841.0, 1849.0, 1856.0, 1863.0, 1871.0, 1878.0, 1885.0, 1893.0, 1901.0, 1908.0, 1915.0, 1923.0, 1930.0, 1938.0, 1946.0, 1953.0, 1961.0, 1969.0, 1976.0, 1984.0, 1992.0, 2000.0, 2007.0, 2015.0, 2023.0, 2031.0, 2039.0, 2047.0, 2055.0, 2063.0, 2071.0, 2079.0, 2087.0, 2095.0, 2104.0, 2112.0, 2120.0, 2128.0, 2137.0, 2146.0, 2154.0, 2162.0, 2171.0, 2179.0, 2188.0, 2197.0, 2205.0, 2214.0, 2223.0, 2232.0, 2241.0, 2250.0, 2258.0, 2268.0, 2277.0, 2285.0, 2294.0, 2304.0, 2313.0, 2322.0, 2331.0, 2340.0, 2350.0, 2359.0, 2368.0, 2378.0, 2388.0, 2397.0, 2407.0, 2416.0, 2426.0, 2436.0, 2446.0, 2455.0, 2465.0, 2475.0, 2485.0, 2495.0, 2505.0, 2515.0, 2525.0, 2535.0, 2545.0, 2556.0, 2566.0, 2577.0, 2587.0, 2598.0, 2609.0, 2620.0, 2631.0, 2641.0, 2652.0, 2663.0, 2674.0, 2685.0, 2696.0, 2708.0, 2719.0, 2730.0, 2742.0, 2753.0, 2764.0, 2776.0, 2788.0, 2799.0, 2811.0, 2823.0, 2835.0, 2847.0, 2858.0, 2870.0, 2882.0, 2894.0, 2906.0, 2919.0, 2931.0, 2943.0, 2956.0, 2968.0, 2981.0, 2994.0, 3006.0, 3019.0, 3032.0, 3045.0, 3058.0, 3070.0, 3083.0, 3096.0, 3109.0, 3121.0, 3134.0, 3148.0, 3161.0, 3174.0, 3187.0, 3200.0, 3214.0, 3228.0, 3242.0, 3255.0, 3268.0, 3283.0, 3297.0, 3310.0, 3325.0, 3340.0, 3353.0, 3368.0, 3383.0, 3398.0, 3412.0, 3427.0, 3442.0, 3457.0, 3471.0, 3487.0, 3502.0, 3516.0, 3531.0, 3546.0, 3561.0, 3577.0, 3593.0, 3608.0, 3625.0, 3641.0, 3657.0, 3673.0, 3690.0, 3706.0, 3722.0, 3738.0, 3755.0, 3772.0, 3789.0, 3805.0, 3823.0, 3839.0, 3856.0, 3873.0, 3891.0, 3908.0, 3926.0, 3944.0, 3960.0, 3977.0, 3995.0, 4013.0, 4031.0, 4048.0, 4067.0, 4085.0, 4104.0, 4122.0, 4140.0, 4159.0, 4177.0, 4196.0, 4215.0, 4234.0, 4253.0, 4272.0, 4291.0, 4311.0, 4332.0, 4351.0, 4371.0, 4391.0, 4412.0, 4433.0, 4454.0, 4474.0, 4496.0, 4518.0, 4538.0, 4558.0, 4579.0, 4601.0, 4619.0, 4640.0, 4662.0, 4684.0, 4706.0, 4728.0, 4751.0, 4771.0, 4794.0, 4818.0, 4840.0, 4863.0, 4887.0, 4910.0, 4933.0, 4956.0, 4980.0, 5004.0, 5028.0, 5052.0, 5076.0, 5100.0, 5125.0, 5152.0, 5175.0, 5200.0, 5226.0, 5251.0, 5278.0, 5304.0, 5329.0, 5354.0, 5381.0, 5407.0, 5433.0, 5460.0, 5488.0, 5516.0, 5544.0, 5573.0, 5600.0, 5628.0, 5656.0, 5684.0, 5713.0, 5741.0, 5771.0, 5799.0, 5830.0, 5860.0, 5891.0, 5921.0, 5951.0, 5980.0, 6010.0, 6041.0, 6073.0, 6105.0, 6133.0, 6163.0, 6195.0, 6227.0, 6258.0, 6291.0, 6322.0, 6356.0, 6390.0, 6424.0, 6457.0, 6491.0, 6527.0, 6561.0, 6596.0, 6631.0, 6665.0, 6701.0, 6736.0, 6771.0, 6805.0, 6840.0, 6877.0, 6911.0, 6947.0, 6985.0, 7022.0, 7059.0, 7097.0, 7135.0, 7174.0, 7212.0, 7251.0, 7289.0, 7327.0, 7366.0, 7406.0, 7447.0, 7486.0, 7525.0, 7566.0, 7606.0, 7646.0, 7688.0, 7728.0, 7771.0, 7814.0, 7859.0, 7901.0, 7949.0, 7992.0, 8036.0, 8082.0, 8127.0, 8173.0, 8218.0, 8262.0, 8309.0, 8353.0, 8397.0, 8444.0, 8489.0, 8539.0, 8585.0, 8632.0, 8682.0, 8727.0, 8777.0, 8828.0, 8879.0, 8929.0, 8982.0, 9037.0, 9087.0, 9140.0, 9193.0, 9250.0, 9305.0, 9361.0, 9418.0, 9475.0, 9532.0, 9589.0, 9644.0, 9699.0, 9758.0, 9818.0, 9875.0, 9935.0, 9997.0, 10057.0, 10117.0, 10174.0, 10232.0, 10296.0, 10356.0, 10419.0, 10482.0, 10546.0, 10608.0, 10670.0, 10729.0, 10790.0, 10855.0, 10920.0, 10990.0, 11054.0, 11118.0, 11181.0, 11248.0, 11316.0, 11385.0, 11454.0, 11526.0, 11597.0, 11667.0, 11740.0, 11820.0, 11897.0, 11973.0, 12046.0, 12126.0, 12204.0, 12287.0, 12370.0, 12456.0, 12538.0, 12627.0, 12714.0, 12799.0, 12883.0, 12971.0, 13062.0, 13154.0, 13233.0, 13328.0, 13418.0, 13511.0, 13607.0, 13709.0, 13806.0, 13903.0, 14002.0, 14104.0, 14200.0, 14288.0, 14391.0, 14488.0, 14590.0, 14698.0, 14808.0, 14910.0, 15020.0, 15126.0, 15238.0, 15347.0, 15456.0, 15574.0, 15692.0, 15786.0, 15896.0, 16016.0, 16136.0, 16250.0, 16352.0, 16474.0, 16575.0, 16702.0, 16835.0, 16965.0, 17096.0, 17232.0, 17370.0, 17443.0, 17581.0, 17719.0, 17864.0, 17976.0, 18116.0, 18250.0, 18396.0, 18540.0, 18690.0, 18840.0, 18989.0, 19136.0, 19294.0, 19445.0, 19589.0, 19750.0, 19905.0, 20064.0, 20191.0, 20325.0, 20497.0, 20662.0, 20833.0, 20981.0, 21152.0, 21334.0, 21510.0, 21642.0, 21821.0, 22001.0, 22186.0, 22379.0, 22568.0, 22770.0, 22958.0, 23162.0, 23360.0, 23524.0, 23737.0, 23960.0, 24175.0, 24395.0, 24631.0, 24865.0, 25091.0, 25327.0, 25580.0, 25833.0, 26089.0, 26361.0, 26636.0, 26889.0, 27155.0, 27436.0, 27715.0, 28003.0, 28303.0, 28600.0, 28916.0, 29223.0, 29553.0, 29884.0, 30200.0, 30538.0, 30868.0, 31211.0, 31548.0, 31881.0, 32253.0, 32605.0, 32980.0, 33385.0, 33805.0, 34254.0, 34723.0, 35167.0, 35666.0, 36125.0, 36652.0, 37177.0, 37739.0, 38321.0, 38932.0, 39640.0, 40337.0, 41000.0, 41626.0, 42385.0, 43122.0, 43890.0, 44687.0, 45609.0, 46520.0, 47489.0, 48432.0, 49458.0, 50511.0, 51561.0, 52568.0, 53676.0, 54936.0, 56071.0, 57302.0, 58513.0, 59800.0, 61192.0, 62702.0, 64205.0, 65868.0, 67780.0, 69960.0, 72330.0, 74918.0, 77540.0, 80344.0, 83727.0, 87662.0, 93589.0, 101441.0, 110544.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 106 + local_name: "variables" + } + children { + node_id: 107 + local_name: "regularization_losses" + } + children { + node_id: 108 + local_name: "trainable_variables" + } + children { + node_id: 109 + local_name: "keras_api" + } + children { + node_id: 242 + local_name: "__call__" + } + children { + node_id: 243 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_9\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_9\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAgAAAAQAAAATAAAAcxgAAACIAHwAgwF9AXQAagF8AXQAagJkAY0CUwApAk4pAdoF\\nZHR5cGUpA9oCdGbaCnplcm9zX2xpa2XaB2Zsb2F0MzIpAtoDb2Jz2gxleHBhbmRlZF9vYnMpAdoO\\nZXhwYW5kX2RpbXNfb3CpAPr0L2V4cG9ydC9oZGEzL2JvcmdsZXQvbG9jYWxfcmFtX2ZzX2RpcnMv\\nMC55dW5kaV9tdXBwZXRfMF8xMjI3MDgzMy4xMy55dW5kaS4xOTQ3MzE0MTc5NjEuOGY0ZjlmOThj\\nYjdhMzA1NS9idWlsZF90YXJnZXRfdHJhaW5fcGFyX2Q5NzU3NTM3MDE2YTJlYjgvdHJhaW4ucGFy\\nL2dvb2dsZTMvbGVhcm5pbmcvc21hcnRjaG9pY2VzL3Jlc2VhcmNoL2NsaWVudHMvY29tcGlsZXJf\\nb3B0L3BvbGljeV90cmFpbmluZy9mZWF0dXJlX29wcy5wedoPZGlzY2FyZF9mZWF0dXJlJwAAAHME\\nAAAAAAEIAQ==\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 110 + local_name: "variables" + } + children { + node_id: 111 + local_name: "regularization_losses" + } + children { + node_id: 112 + local_name: "trainable_variables" + } + children { + node_id: 113 + local_name: "keras_api" + } + children { + node_id: 244 + local_name: "__call__" + } + children { + node_id: 245 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_10\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_10\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [13.0, 38.0, 56.0, 70.0, 82.0, 94.0, 104.0, 114.0, 123.0, 131.0, 139.0, 148.0, 152.0, 153.0, 158.0, 163.0, 170.0, 174.0, 178.0, 180.0, 183.0, 186.0, 188.0, 190.0, 192.0, 196.0, 198.0, 201.0, 205.0, 208.0, 212.0, 215.0, 219.0, 221.0, 225.0, 227.0, 229.0, 232.0, 233.0, 236.0, 239.0, 242.0, 245.0, 248.0, 250.0, 252.0, 254.0, 256.0, 259.0, 261.0, 264.0, 267.0, 270.0, 272.0, 275.0, 278.0, 280.0, 283.0, 285.0, 287.0, 290.0, 293.0, 295.0, 297.0, 300.0, 303.0, 305.0, 308.0, 311.0, 313.0, 316.0, 319.0, 322.0, 325.0, 329.0, 331.0, 333.0, 336.0, 338.0, 340.0, 343.0, 345.0, 347.0, 347.0, 349.0, 351.0, 353.0, 355.0, 357.0, 359.0, 361.0, 363.0, 365.0, 368.0, 369.0, 371.0, 373.0, 375.0, 377.0, 380.0, 382.0, 385.0, 387.0, 389.0, 391.0, 394.0, 396.0, 398.0, 400.0, 403.0, 405.0, 408.0, 410.0, 412.0, 415.0, 417.0, 420.0, 422.0, 425.0, 427.0, 429.0, 432.0, 434.0, 437.0, 439.0, 442.0, 444.0, 446.0, 449.0, 451.0, 454.0, 456.0, 458.0, 461.0, 463.0, 466.0, 469.0, 472.0, 474.0, 476.0, 479.0, 482.0, 483.0, 486.0, 489.0, 492.0, 495.0, 498.0, 500.0, 503.0, 505.0, 508.0, 510.0, 513.0, 516.0, 519.0, 522.0, 524.0, 528.0, 530.0, 533.0, 536.0, 539.0, 541.0, 544.0, 547.0, 550.0, 553.0, 556.0, 559.0, 561.0, 563.0, 567.0, 570.0, 572.0, 575.0, 577.0, 580.0, 584.0, 586.0, 589.0, 592.0, 595.0, 598.0, 601.0, 605.0, 607.0, 611.0, 613.0, 617.0, 620.0, 623.0, 626.0, 629.0, 632.0, 635.0, 639.0, 642.0, 645.0, 648.0, 651.0, 654.0, 657.0, 660.0, 662.0, 666.0, 669.0, 672.0, 676.0, 679.0, 682.0, 685.0, 688.0, 690.0, 693.0, 696.0, 699.0, 702.0, 705.0, 709.0, 712.0, 714.0, 718.0, 721.0, 724.0, 726.0, 728.0, 729.0, 731.0, 734.0, 737.0, 741.0, 745.0, 748.0, 750.0, 753.0, 756.0, 760.0, 763.0, 766.0, 770.0, 773.0, 776.0, 779.0, 782.0, 786.0, 788.0, 793.0, 796.0, 798.0, 802.0, 805.0, 808.0, 811.0, 815.0, 818.0, 820.0, 824.0, 827.0, 829.0, 832.0, 835.0, 838.0, 842.0, 846.0, 849.0, 854.0, 857.0, 860.0, 864.0, 867.0, 871.0, 875.0, 879.0, 882.0, 887.0, 890.0, 893.0, 897.0, 901.0, 905.0, 908.0, 911.0, 915.0, 918.0, 921.0, 925.0, 929.0, 932.0, 934.0, 937.0, 940.0, 943.0, 946.0, 950.0, 953.0, 956.0, 961.0, 965.0, 969.0, 973.0, 976.0, 980.0, 982.0, 985.0, 990.0, 994.0, 997.0, 1001.0, 1005.0, 1007.0, 1010.0, 1014.0, 1018.0, 1022.0, 1025.0, 1028.0, 1033.0, 1035.0, 1038.0, 1042.0, 1047.0, 1052.0, 1056.0, 1060.0, 1063.0, 1067.0, 1071.0, 1075.0, 1079.0, 1083.0, 1086.0, 1088.0, 1092.0, 1097.0, 1102.0, 1106.0, 1109.0, 1113.0, 1117.0, 1120.0, 1125.0, 1129.0, 1134.0, 1137.0, 1142.0, 1146.0, 1150.0, 1151.0, 1155.0, 1159.0, 1162.0, 1166.0, 1170.0, 1174.0, 1177.0, 1181.0, 1185.0, 1188.0, 1193.0, 1196.0, 1203.0, 1207.0, 1212.0, 1214.0, 1217.0, 1220.0, 1222.0, 1222.0, 1226.0, 1229.0, 1233.0, 1237.0, 1241.0, 1246.0, 1250.0, 1253.0, 1257.0, 1262.0, 1267.0, 1272.0, 1278.0, 1283.0, 1287.0, 1293.0, 1297.0, 1301.0, 1304.0, 1309.0, 1315.0, 1320.0, 1325.0, 1329.0, 1333.0, 1336.0, 1341.0, 1344.0, 1348.0, 1351.0, 1357.0, 1363.0, 1368.0, 1374.0, 1379.0, 1383.0, 1386.0, 1391.0, 1395.0, 1399.0, 1403.0, 1407.0, 1410.0, 1415.0, 1418.0, 1423.0, 1428.0, 1432.0, 1436.0, 1438.0, 1442.0, 1446.0, 1450.0, 1454.0, 1462.0, 1467.0, 1472.0, 1477.0, 1483.0, 1488.0, 1492.0, 1496.0, 1503.0, 1508.0, 1513.0, 1518.0, 1520.0, 1526.0, 1531.0, 1534.0, 1538.0, 1542.0, 1546.0, 1552.0, 1558.0, 1564.0, 1568.0, 1573.0, 1578.0, 1581.0, 1590.0, 1596.0, 1601.0, 1606.0, 1611.0, 1616.0, 1622.0, 1629.0, 1634.0, 1640.0, 1647.0, 1651.0, 1657.0, 1660.0, 1665.0, 1672.0, 1678.0, 1686.0, 1692.0, 1698.0, 1704.0, 1709.0, 1714.0, 1719.0, 1724.0, 1730.0, 1737.0, 1744.0, 1751.0, 1755.0, 1761.0, 1764.0, 1772.0, 1778.0, 1784.0, 1789.0, 1799.0, 1804.0, 1811.0, 1819.0, 1825.0, 1830.0, 1838.0, 1849.0, 1858.0, 1862.0, 1868.0, 1872.0, 1878.0, 1885.0, 1888.0, 1892.0, 1897.0, 1902.0, 1907.0, 1919.0, 1926.0, 1932.0, 1936.0, 1941.0, 1946.0, 1952.0, 1960.0, 1968.0, 1977.0, 1985.0, 1992.0, 1997.0, 2006.0, 2012.0, 2018.0, 2026.0, 2034.0, 2044.0, 2050.0, 2057.0, 2064.0, 2069.0, 2075.0, 2082.0, 2091.0, 2098.0, 2107.0, 2122.0, 2126.0, 2135.0, 2146.0, 2149.0, 2157.0, 2163.0, 2172.0, 2178.0, 2184.0, 2191.0, 2198.0, 2208.0, 2216.0, 2223.0, 2235.0, 2242.0, 2252.0, 2263.0, 2272.0, 2277.0, 2288.0, 2296.0, 2306.0, 2311.0, 2318.0, 2323.0, 2334.0, 2341.0, 2356.0, 2366.0, 2373.0, 2379.0, 2386.0, 2407.0, 2416.0, 2423.0, 2432.0, 2438.0, 2448.0, 2453.0, 2464.0, 2473.0, 2473.0, 2481.0, 2492.0, 2504.0, 2511.0, 2523.0, 2529.0, 2537.0, 2545.0, 2556.0, 2566.0, 2575.0, 2584.0, 2592.0, 2602.0, 2613.0, 2624.0, 2636.0, 2643.0, 2647.0, 2652.0, 2664.0, 2675.0, 2688.0, 2693.0, 2702.0, 2709.0, 2722.0, 2739.0, 2754.0, 2766.0, 2776.0, 2786.0, 2799.0, 2810.0, 2832.0, 2840.0, 2849.0, 2860.0, 2873.0, 2889.0, 2908.0, 2914.0, 2926.0, 2939.0, 2950.0, 2961.0, 2969.0, 2978.0, 2990.0, 2999.0, 3023.0, 3032.0, 3049.0, 3066.0, 3085.0, 3101.0, 3107.0, 3117.0, 3129.0, 3144.0, 3167.0, 3190.0, 3212.0, 3229.0, 3238.0, 3264.0, 3293.0, 3302.0, 3309.0, 3314.0, 3323.0, 3344.0, 3352.0, 3362.0, 3390.0, 3400.0, 3411.0, 3435.0, 3456.0, 3470.0, 3485.0, 3498.0, 3505.0, 3519.0, 3539.0, 3545.0, 3545.0, 3560.0, 3576.0, 3597.0, 3607.0, 3621.0, 3641.0, 3665.0, 3679.0, 3701.0, 3714.0, 3733.0, 3741.0, 3745.0, 3757.0, 3773.0, 3787.0, 3795.0, 3805.0, 3822.0, 3835.0, 3844.0, 3861.0, 3872.0, 3878.0, 3897.0, 3919.0, 3941.0, 3971.0, 4004.0, 4014.0, 4019.0, 4061.0, 4068.0, 4089.0, 4108.0, 4117.0, 4125.0, 4146.0, 4165.0, 4194.0, 4204.0, 4224.0, 4236.0, 4263.0, 4290.0, 4301.0, 4319.0, 4326.0, 4347.0, 4369.0, 4386.0, 4413.0, 4435.0, 4451.0, 4451.0, 4451.0, 4476.0, 4500.0, 4539.0, 4579.0, 4592.0, 4600.0, 4622.0, 4650.0, 4683.0, 4714.0, 4742.0, 4755.0, 4771.0, 4788.0, 4816.0, 4828.0, 4831.0, 4831.0, 4831.0, 4843.0, 4852.0, 4865.0, 4896.0, 4915.0, 4931.0, 4952.0, 4965.0, 4983.0, 5007.0, 5043.0, 5061.0, 5081.0, 5095.0, 5122.0, 5143.0, 5171.0, 5204.0, 5226.0, 5233.0, 5250.0, 5281.0, 5320.0, 5323.0, 5328.0, 5345.0, 5374.0, 5413.0, 5466.0, 5492.0, 5524.0, 5555.0, 5567.0, 5610.0, 5676.0, 5701.0, 5716.0, 5744.0, 5768.0, 5795.0, 5818.0, 5854.0, 5906.0, 5934.0, 5960.0, 5975.0, 5993.0, 6025.0, 6034.0, 6051.0, 6082.0, 6106.0, 6125.0, 6159.0, 6187.0, 6242.0, 6287.0, 6311.0, 6332.0, 6348.0, 6358.0, 6368.0, 6377.0, 6402.0, 6407.0, 6428.0, 6450.0, 6475.0, 6498.0, 6505.0, 6533.0, 6565.0, 6580.0, 6595.0, 6611.0, 6654.0, 6658.0, 6705.0, 6751.0, 6786.0, 6828.0, 6876.0, 6896.0, 6948.0, 6964.0, 7065.0, 7082.0, 7118.0, 7184.0, 7214.0, 7271.0, 7310.0, 7357.0, 7405.0, 7506.0, 7613.0, 7641.0, 7675.0, 7720.0, 7781.0, 7833.0, 7860.0, 7898.0, 7929.0, 8044.0, 8104.0, 8148.0, 8236.0, 8273.0, 8313.0, 8349.0, 8381.0, 8409.0, 8498.0, 8507.0, 8524.0, 8570.0, 8607.0, 8630.0, 8637.0, 8675.0, 8700.0, 8714.0, 8734.0, 8776.0, 8836.0, 8854.0, 8867.0, 8868.0, 9065.0, 9113.0, 9121.0, 9241.0, 9357.0, 9360.0, 9585.0, 9613.0, 9684.0, 9727.0, 9751.0, 9777.0, 9802.0, 9889.0, 9903.0, 9914.0, 9978.0, 10061.0, 10192.0, 10213.0, 10345.0, 10369.0, 10404.0, 10430.0, 10471.0, 10481.0, 10489.0, 10492.0, 10494.0, 10524.0, 10554.0, 10557.0, 10560.0, 10562.0, 10641.0, 10716.0, 10842.0, 10897.0, 10967.0, 11053.0, 11128.0, 11137.0, 11328.0, 11336.0, 11401.0, 11532.0, 11573.0, 11860.0, 11880.0, 12013.0, 12305.0, 12358.0, 12386.0, 12404.0, 12456.0, 12456.0, 12476.0, 12615.0, 12677.0, 12981.0, 13094.0, 13197.0, 13708.0, 13717.0, 13788.0, 14049.0, 14112.0, 14224.0, 14257.0, 14681.0, 14901.0, 15006.0, 15071.0, 15100.0, 15248.0, 15669.0, 15877.0, 15953.0, 15953.0, 16066.0, 16072.0, 16271.0, 16292.0, 16386.0, 16490.0, 16633.0, 16670.0, 16834.0, 16896.0, 17543.0, 17693.0, 17800.0, 17859.0, 18397.0, 18811.0, 18826.0, 18971.0, 19304.0, 19319.0, 19695.0, 20378.0, 20865.0, 21313.0, 21330.0, 22321.0, 22760.0, 22770.0, 23783.0, 23785.0, 24525.0, 24844.0, 24848.0, 24964.0, 24966.0, 27468.0, 27478.0, 27555.0, 27555.0, 28215.0, 28219.0, 28336.0, 28490.0, 30213.0, 30228.0, 30242.0, 34116.0, 43518.0, 43518.0, 43518.0, 43852.0, 43852.0, 43852.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + children { + node_id: 114 + local_name: "variables" + } + children { + node_id: 115 + local_name: "regularization_losses" + } + children { + node_id: 116 + local_name: "trainable_variables" + } + children { + node_id: 117 + local_name: "keras_api" + } + children { + node_id: 246 + local_name: "__call__" + } + children { + node_id: 247 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Lambda\", \"name\": \"lambda_11\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"lambda_11\", \"trainable\": true, \"dtype\": \"float32\", \"function\": {\"class_name\": \"__tuple__\", \"items\": [\"4wEAAAAAAAAAAwAAAAUAAAATAAAAc0QAAACIAHwAgwF9AXQAagF0AmoDfAGIAYMCdABqBIMCdAWI\\nAYMBGwB9AnQAagZ8AnQAagd8AoMBfAJ8AhQAZwNkA2QCjQJTACkETukBAAAAKQHaBGF4aXPp////\\n/ykI2gJ0ZtoEY2FzdNoOY29udHJpYl9sYXllcnPaCWJ1Y2tldGl6ZdoHZmxvYXQzMtoDbGVu2gZj\\nb25jYXTaBHNxcnQpA9oDb2Jz2gxleHBhbmRlZF9vYnPaAXgpAtoOZXhwYW5kX2RpbXNfb3DaCHF1\\nYW50aWxlqQD69C9leHBvcnQvaGRhMy9ib3JnbGV0L2xvY2FsX3JhbV9mc19kaXJzLzAueXVuZGlf\\nbXVwcGV0XzBfMTIyNzA4MzMuMTMueXVuZGkuMTk0NzMxNDE3OTYxLjhmNGY5Zjk4Y2I3YTMwNTUv\\nYnVpbGRfdGFyZ2V0X3RyYWluX3Bhcl9kOTc1NzUzNzAxNmEyZWI4L3RyYWluLnBhci9nb29nbGUz\\nL2xlYXJuaW5nL3NtYXJ0Y2hvaWNlcy9yZXNlYXJjaC9jbGllbnRzL2NvbXBpbGVyX29wdC9wb2xp\\nY3lfdHJhaW5pbmcvZmVhdHVyZV9vcHMucHnaDW5vcm1hbGl6YXRpb24wAAAAcwoAAAAAAQgBBAEK\\nARAB\\n\", null, {\"class_name\": \"__tuple__\", \"items\": [{\"class_name\": \"ExpandDims\", \"config\": {\"name\": \"expand_dims\", \"trainable\": true, \"dtype\": \"float32\", \"axis\": -1}}, [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 4.0]]}]}, \"function_type\": \"lambda\", \"module\": \"google3.learning.smartchoices.research.clients.compiler_opt.policy_training.feature_ops\", \"output_shape\": null, \"output_shape_type\": \"raw\", \"output_shape_module\": null, \"arguments\": {}}}" + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 118 + local_name: "layer_metrics" + } + children { + node_id: 53 + local_name: "variables" + } + children { + node_id: 119 + local_name: "layer_regularization_losses" + } + children { + node_id: 120 + local_name: "metrics" + } + children { + node_id: 121 + local_name: "layers" + } + children { + node_id: 54 + local_name: "regularization_losses" + } + children { + node_id: 122 + local_name: "non_trainable_variables" + } + children { + node_id: 55 + local_name: "trainable_variables" + } + children { + node_id: 222 + local_name: "__call__" + } + children { + node_id: 223 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 223 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 123 + local_name: "variables" + } + children { + node_id: 124 + local_name: "regularization_losses" + } + children { + node_id: 125 + local_name: "trainable_variables" + } + children { + node_id: 126 + local_name: "keras_api" + } + children { + node_id: 248 + local_name: "__call__" + } + children { + node_id: 249 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Flatten\", \"name\": \"flatten\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"flatten\", \"trainable\": true, \"dtype\": \"float32\", \"data_format\": \"channels_last\"}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 1, \"axes\": {}}}}" + } + } + nodes { + children { + node_id: 10 + local_name: "kernel" + } + children { + node_id: 11 + local_name: "bias" + } + children { + node_id: 127 + local_name: "variables" + } + children { + node_id: 128 + local_name: "regularization_losses" + } + children { + node_id: 129 + local_name: "trainable_variables" + } + children { + node_id: 130 + local_name: "keras_api" + } + children { + node_id: 250 + local_name: "__call__" + } + children { + node_id: 251 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Dense\", \"name\": \"dense\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"VarianceScaling\", \"config\": {\"scale\": 2.0, \"mode\": \"fan_in\", \"distribution\": \"truncated_normal\", \"seed\": null, \"dtype\": \"float32\"}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 34}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [0, 34]}}" + } + } + nodes { + children { + node_id: 12 + local_name: "kernel" + } + children { + node_id: 13 + local_name: "bias" + } + children { + node_id: 131 + local_name: "variables" + } + children { + node_id: 132 + local_name: "regularization_losses" + } + children { + node_id: 133 + local_name: "trainable_variables" + } + children { + node_id: 134 + local_name: "keras_api" + } + children { + node_id: 252 + local_name: "__call__" + } + children { + node_id: 253 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Dense\", \"name\": \"dense_1\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 40, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"VarianceScaling\", \"config\": {\"scale\": 2.0, \"mode\": \"fan_in\", \"distribution\": \"truncated_normal\", \"seed\": null, \"dtype\": \"float32\"}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 100}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [0, 100]}}" + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 41 + local_name: "0" + } + children { + node_id: 42 + local_name: "1" + } + children { + node_id: 43 + local_name: "2" + } + children { + node_id: 44 + local_name: "3" + } + children { + node_id: 45 + local_name: "4" + } + children { + node_id: 46 + local_name: "5" + } + children { + node_id: 47 + local_name: "6" + } + children { + node_id: 48 + local_name: "7" + } + children { + node_id: 49 + local_name: "8" + } + children { + node_id: 50 + local_name: "9" + } + children { + node_id: 51 + local_name: "10" + } + children { + node_id: 52 + local_name: "11" + } + children { + node_id: 26 + local_name: "12" + } + children { + node_id: 57 + local_name: "13" + } + children { + node_id: 58 + local_name: "14" + } + children { + node_id: 59 + local_name: "15" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 135 + local_name: "layer_metrics" + } + children { + node_id: 70 + local_name: "variables" + } + children { + node_id: 136 + local_name: "layer_regularization_losses" + } + children { + node_id: 137 + local_name: "metrics" + } + children { + node_id: 138 + local_name: "layers" + } + children { + node_id: 71 + local_name: "regularization_losses" + } + children { + node_id: 139 + local_name: "non_trainable_variables" + } + children { + node_id: 72 + local_name: "trainable_variables" + } + children { + node_id: 224 + local_name: "__call__" + } + children { + node_id: 225 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 225 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 140 + local_name: "layer_metrics" + } + children { + node_id: 74 + local_name: "variables" + } + children { + node_id: 141 + local_name: "layer_regularization_losses" + } + children { + node_id: 142 + local_name: "metrics" + } + children { + node_id: 143 + local_name: "layers" + } + children { + node_id: 75 + local_name: "regularization_losses" + } + children { + node_id: 144 + local_name: "non_trainable_variables" + } + children { + node_id: 76 + local_name: "trainable_variables" + } + children { + node_id: 226 + local_name: "__call__" + } + children { + node_id: 227 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 227 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 145 + local_name: "layer_metrics" + } + children { + node_id: 78 + local_name: "variables" + } + children { + node_id: 146 + local_name: "layer_regularization_losses" + } + children { + node_id: 147 + local_name: "metrics" + } + children { + node_id: 148 + local_name: "layers" + } + children { + node_id: 79 + local_name: "regularization_losses" + } + children { + node_id: 149 + local_name: "non_trainable_variables" + } + children { + node_id: 80 + local_name: "trainable_variables" + } + children { + node_id: 228 + local_name: "__call__" + } + children { + node_id: 229 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 229 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 150 + local_name: "layer_metrics" + } + children { + node_id: 82 + local_name: "variables" + } + children { + node_id: 151 + local_name: "layer_regularization_losses" + } + children { + node_id: 152 + local_name: "metrics" + } + children { + node_id: 153 + local_name: "layers" + } + children { + node_id: 83 + local_name: "regularization_losses" + } + children { + node_id: 154 + local_name: "non_trainable_variables" + } + children { + node_id: 84 + local_name: "trainable_variables" + } + children { + node_id: 230 + local_name: "__call__" + } + children { + node_id: 231 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 231 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 155 + local_name: "layer_metrics" + } + children { + node_id: 86 + local_name: "variables" + } + children { + node_id: 156 + local_name: "layer_regularization_losses" + } + children { + node_id: 157 + local_name: "metrics" + } + children { + node_id: 158 + local_name: "layers" + } + children { + node_id: 87 + local_name: "regularization_losses" + } + children { + node_id: 159 + local_name: "non_trainable_variables" + } + children { + node_id: 88 + local_name: "trainable_variables" + } + children { + node_id: 232 + local_name: "__call__" + } + children { + node_id: 233 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 233 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 160 + local_name: "layer_metrics" + } + children { + node_id: 90 + local_name: "variables" + } + children { + node_id: 161 + local_name: "layer_regularization_losses" + } + children { + node_id: 162 + local_name: "metrics" + } + children { + node_id: 163 + local_name: "layers" + } + children { + node_id: 91 + local_name: "regularization_losses" + } + children { + node_id: 164 + local_name: "non_trainable_variables" + } + children { + node_id: 92 + local_name: "trainable_variables" + } + children { + node_id: 234 + local_name: "__call__" + } + children { + node_id: 235 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 235 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 165 + local_name: "layer_metrics" + } + children { + node_id: 94 + local_name: "variables" + } + children { + node_id: 166 + local_name: "layer_regularization_losses" + } + children { + node_id: 167 + local_name: "metrics" + } + children { + node_id: 168 + local_name: "layers" + } + children { + node_id: 95 + local_name: "regularization_losses" + } + children { + node_id: 169 + local_name: "non_trainable_variables" + } + children { + node_id: 96 + local_name: "trainable_variables" + } + children { + node_id: 236 + local_name: "__call__" + } + children { + node_id: 237 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 237 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 170 + local_name: "layer_metrics" + } + children { + node_id: 98 + local_name: "variables" + } + children { + node_id: 171 + local_name: "layer_regularization_losses" + } + children { + node_id: 172 + local_name: "metrics" + } + children { + node_id: 173 + local_name: "layers" + } + children { + node_id: 99 + local_name: "regularization_losses" + } + children { + node_id: 174 + local_name: "non_trainable_variables" + } + children { + node_id: 100 + local_name: "trainable_variables" + } + children { + node_id: 238 + local_name: "__call__" + } + children { + node_id: 239 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 239 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 175 + local_name: "layer_metrics" + } + children { + node_id: 102 + local_name: "variables" + } + children { + node_id: 176 + local_name: "layer_regularization_losses" + } + children { + node_id: 177 + local_name: "metrics" + } + children { + node_id: 178 + local_name: "layers" + } + children { + node_id: 103 + local_name: "regularization_losses" + } + children { + node_id: 179 + local_name: "non_trainable_variables" + } + children { + node_id: 104 + local_name: "trainable_variables" + } + children { + node_id: 240 + local_name: "__call__" + } + children { + node_id: 241 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 241 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 180 + local_name: "layer_metrics" + } + children { + node_id: 106 + local_name: "variables" + } + children { + node_id: 181 + local_name: "layer_regularization_losses" + } + children { + node_id: 182 + local_name: "metrics" + } + children { + node_id: 183 + local_name: "layers" + } + children { + node_id: 107 + local_name: "regularization_losses" + } + children { + node_id: 184 + local_name: "non_trainable_variables" + } + children { + node_id: 108 + local_name: "trainable_variables" + } + children { + node_id: 242 + local_name: "__call__" + } + children { + node_id: 243 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 243 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 185 + local_name: "layer_metrics" + } + children { + node_id: 110 + local_name: "variables" + } + children { + node_id: 186 + local_name: "layer_regularization_losses" + } + children { + node_id: 187 + local_name: "metrics" + } + children { + node_id: 188 + local_name: "layers" + } + children { + node_id: 111 + local_name: "regularization_losses" + } + children { + node_id: 189 + local_name: "non_trainable_variables" + } + children { + node_id: 112 + local_name: "trainable_variables" + } + children { + node_id: 244 + local_name: "__call__" + } + children { + node_id: 245 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 245 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 190 + local_name: "layer_metrics" + } + children { + node_id: 114 + local_name: "variables" + } + children { + node_id: 191 + local_name: "layer_regularization_losses" + } + children { + node_id: 192 + local_name: "metrics" + } + children { + node_id: 193 + local_name: "layers" + } + children { + node_id: 115 + local_name: "regularization_losses" + } + children { + node_id: 194 + local_name: "non_trainable_variables" + } + children { + node_id: 116 + local_name: "trainable_variables" + } + children { + node_id: 246 + local_name: "__call__" + } + children { + node_id: 247 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 247 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 195 + local_name: "layer_metrics" + } + children { + node_id: 123 + local_name: "variables" + } + children { + node_id: 196 + local_name: "layer_regularization_losses" + } + children { + node_id: 197 + local_name: "metrics" + } + children { + node_id: 198 + local_name: "layers" + } + children { + node_id: 124 + local_name: "regularization_losses" + } + children { + node_id: 199 + local_name: "non_trainable_variables" + } + children { + node_id: 125 + local_name: "trainable_variables" + } + children { + node_id: 248 + local_name: "__call__" + } + children { + node_id: 249 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 249 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 10 + local_name: "0" + } + children { + node_id: 11 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 10 + local_name: "0" + } + children { + node_id: 11 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 200 + local_name: "layer_metrics" + } + children { + node_id: 127 + local_name: "variables" + } + children { + node_id: 201 + local_name: "layer_regularization_losses" + } + children { + node_id: 202 + local_name: "metrics" + } + children { + node_id: 203 + local_name: "layers" + } + children { + node_id: 128 + local_name: "regularization_losses" + } + children { + node_id: 204 + local_name: "non_trainable_variables" + } + children { + node_id: 129 + local_name: "trainable_variables" + } + children { + node_id: 250 + local_name: "__call__" + } + children { + node_id: 251 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 251 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 12 + local_name: "0" + } + children { + node_id: 13 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 12 + local_name: "0" + } + children { + node_id: 13 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 205 + local_name: "layer_metrics" + } + children { + node_id: 131 + local_name: "variables" + } + children { + node_id: 206 + local_name: "layer_regularization_losses" + } + children { + node_id: 207 + local_name: "metrics" + } + children { + node_id: 208 + local_name: "layers" + } + children { + node_id: 132 + local_name: "regularization_losses" + } + children { + node_id: 209 + local_name: "non_trainable_variables" + } + children { + node_id: 133 + local_name: "trainable_variables" + } + children { + node_id: 252 + local_name: "__call__" + } + children { + node_id: 253 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 253 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + function { + concrete_functions: "__inference_polymorphic_action_fn_4619080" + concrete_functions: "__inference_polymorphic_action_fn_946" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "time_step" + } + values { + string_value: "policy_state" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + tuple_value { + values { + tuple_value { + } + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + concrete_functions: "__inference_function_722" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + input_signature { + none_value { + } + } + } + } + } + nodes { + bare_concrete_function { + concrete_function_name: "__inference__728" + } + } + nodes { + bare_concrete_function { + concrete_function_name: "__inference_signature_wrapper_4619026" + argument_keywords: "callee_basic_block_count" + argument_keywords: "callee_conditionally_executed_blocks" + argument_keywords: "callee_users" + argument_keywords: "caller_basic_block_count" + argument_keywords: "caller_conditionally_executed_blocks" + argument_keywords: "caller_users" + argument_keywords: "callsite_height" + argument_keywords: "cost_estimate" + argument_keywords: "discount" + argument_keywords: "edge_count" + argument_keywords: "inlining_default" + argument_keywords: "node_count" + argument_keywords: "nr_ctant_params" + argument_keywords: "reward" + argument_keywords: "step_type" + } + } + nodes { + bare_concrete_function { + concrete_function_name: "__inference_signature_wrapper_4619033" + } + } + nodes { + bare_concrete_function { + concrete_function_name: "__inference_signature_wrapper_4619048" + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "observation" + } + values { + string_value: "step_type" + } + values { + string_value: "network_state" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + tuple_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "observation" + } + values { + string_value: "step_type" + } + values { + string_value: "network_state" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + tuple_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "observation" + } + values { + string_value: "step_type" + } + values { + string_value: "network_state" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + tuple_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "observation" + } + values { + string_value: "step_type" + } + values { + string_value: "network_state" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + tuple_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "mask" + } + values { + string_value: "training" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + none_value { + } + } + values { + bool_value: false + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + concrete_functions { + key: "__inference__728" + value { + bound_inputs: 4 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + } + } + values { + dict_value { + } + } + } + } + output_signature { + tensor_spec_value { + shape { + } + dtype: DT_INT64 + } + } + } + } + concrete_functions { + key: "__inference_function_722" + value { + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + } + } + values { + dict_value { + } + } + } + } + output_signature { + tuple_value { + } + } + } + } + concrete_functions { + key: "__inference_polymorphic_action_fn_4619080" + value { + bound_inputs: 10 + bound_inputs: 11 + bound_inputs: 12 + bound_inputs: 13 + bound_inputs: 14 + bound_inputs: 15 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + named_tuple_value { + name: "TimeStep" + values { + key: "step_type" + value { + tensor_spec_value { + name: "time_step/step_type" + shape { + dim { + size: 1 + } + } + dtype: DT_INT32 + } + } + } + values { + key: "reward" + value { + tensor_spec_value { + name: "time_step/reward" + shape { + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + values { + key: "discount" + value { + tensor_spec_value { + name: "time_step/discount" + shape { + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + values { + key: "observation" + value { + dict_value { + fields { + key: "callee_basic_block_count" + value { + tensor_spec_value { + name: "time_step/observation/callee_basic_block_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callee_conditionally_executed_blocks" + value { + tensor_spec_value { + name: "time_step/observation/callee_conditionally_executed_blocks" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callee_users" + value { + tensor_spec_value { + name: "time_step/observation/callee_users" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_basic_block_count" + value { + tensor_spec_value { + name: "time_step/observation/caller_basic_block_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_conditionally_executed_blocks" + value { + tensor_spec_value { + name: "time_step/observation/caller_conditionally_executed_blocks" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_users" + value { + tensor_spec_value { + name: "time_step/observation/caller_users" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callsite_height" + value { + tensor_spec_value { + name: "time_step/observation/callsite_height" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "cost_estimate" + value { + tensor_spec_value { + name: "time_step/observation/cost_estimate" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "edge_count" + value { + tensor_spec_value { + name: "time_step/observation/edge_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "inlining_default" + value { + tensor_spec_value { + name: "time_step/observation/inlining_default" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "node_count" + value { + tensor_spec_value { + name: "time_step/observation/node_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "nr_ctant_params" + value { + tensor_spec_value { + name: "time_step/observation/nr_ctant_params" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + } + } + } + } + } + values { + tuple_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + named_tuple_value { + name: "PolicyStep" + values { + key: "action" + value { + tensor_spec_value { + name: "action" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + values { + key: "state" + value { + tuple_value { + } + } + } + values { + key: "info" + value { + tuple_value { + } + } + } + } + } + } + } + concrete_functions { + key: "__inference_polymorphic_action_fn_946" + value { + bound_inputs: 10 + bound_inputs: 11 + bound_inputs: 12 + bound_inputs: 13 + bound_inputs: 14 + bound_inputs: 15 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + named_tuple_value { + name: "TimeStep" + values { + key: "step_type" + value { + tensor_spec_value { + name: "step_type" + shape { + dim { + size: 1 + } + } + dtype: DT_INT32 + } + } + } + values { + key: "reward" + value { + tensor_spec_value { + name: "reward" + shape { + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + values { + key: "discount" + value { + tensor_spec_value { + name: "discount" + shape { + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + values { + key: "observation" + value { + dict_value { + fields { + key: "callee_basic_block_count" + value { + tensor_spec_value { + name: "callee_basic_block_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callee_conditionally_executed_blocks" + value { + tensor_spec_value { + name: "callee_conditionally_executed_blocks" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callee_users" + value { + tensor_spec_value { + name: "callee_users" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_basic_block_count" + value { + tensor_spec_value { + name: "caller_basic_block_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_conditionally_executed_blocks" + value { + tensor_spec_value { + name: "caller_conditionally_executed_blocks" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_users" + value { + tensor_spec_value { + name: "caller_users" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callsite_height" + value { + tensor_spec_value { + name: "callsite_height" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "cost_estimate" + value { + tensor_spec_value { + name: "cost_estimate" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "edge_count" + value { + tensor_spec_value { + name: "edge_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "inlining_default" + value { + tensor_spec_value { + name: "inlining_default" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "node_count" + value { + tensor_spec_value { + name: "node_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "nr_ctant_params" + value { + tensor_spec_value { + name: "nr_ctant_params" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + } + } + } + } + } + values { + tuple_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + named_tuple_value { + name: "PolicyStep" + values { + key: "action" + value { + tensor_spec_value { + name: "action" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + values { + key: "state" + value { + tuple_value { + } + } + } + values { + key: "info" + value { + tuple_value { + } + } + } + } + } + } + } + concrete_functions { + key: "__inference_signature_wrapper_4619026" + value { + bound_inputs: 10 + bound_inputs: 11 + bound_inputs: 12 + bound_inputs: 13 + bound_inputs: 14 + bound_inputs: 15 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + } + } + values { + dict_value { + fields { + key: "callee_basic_block_count" + value { + tensor_spec_value { + name: "callee_basic_block_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callee_conditionally_executed_blocks" + value { + tensor_spec_value { + name: "callee_conditionally_executed_blocks" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callee_users" + value { + tensor_spec_value { + name: "callee_users" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_basic_block_count" + value { + tensor_spec_value { + name: "caller_basic_block_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_conditionally_executed_blocks" + value { + tensor_spec_value { + name: "caller_conditionally_executed_blocks" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "caller_users" + value { + tensor_spec_value { + name: "caller_users" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "callsite_height" + value { + tensor_spec_value { + name: "callsite_height" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "cost_estimate" + value { + tensor_spec_value { + name: "cost_estimate" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "discount" + value { + tensor_spec_value { + name: "discount" + shape { + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + fields { + key: "edge_count" + value { + tensor_spec_value { + name: "edge_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "inlining_default" + value { + tensor_spec_value { + name: "inlining_default" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "node_count" + value { + tensor_spec_value { + name: "node_count" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "nr_ctant_params" + value { + tensor_spec_value { + name: "nr_ctant_params" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + fields { + key: "reward" + value { + tensor_spec_value { + name: "reward" + shape { + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + fields { + key: "step_type" + value { + tensor_spec_value { + name: "step_type" + shape { + dim { + size: 1 + } + } + dtype: DT_INT32 + } + } + } + } + } + } + } + output_signature { + dict_value { + fields { + key: "inlining_decision" + value { + tensor_spec_value { + name: "inlining_decision" + shape { + dim { + size: 1 + } + } + dtype: DT_INT64 + } + } + } + } + } + } + } + concrete_functions { + key: "__inference_signature_wrapper_4619033" + value { + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + } + } + values { + dict_value { + } + } + } + } + output_signature { + dict_value { + } + } + } + } + concrete_functions { + key: "__inference_signature_wrapper_4619048" + value { + bound_inputs: 4 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + } + } + values { + dict_value { + } + } + } + } + output_signature { + dict_value { + fields { + key: "int64" + value { + tensor_spec_value { + name: "int64" + shape { + } + dtype: DT_INT64 + } + } + } + } + } + } + } + } +} + diff --git a/llvm/lib/Analysis/models/inliner/variables/variables.data-00001-of-00002 b/llvm/lib/Analysis/models/inliner/variables/variables.data-00000-of-00001 similarity index 77% rename from llvm/lib/Analysis/models/inliner/variables/variables.data-00001-of-00002 rename to llvm/lib/Analysis/models/inliner/variables/variables.data-00000-of-00001 index 1f1f1b151a71ff4d41aa8b5c1c1107364654a2e3..ee7d7060867e7a36b36ae8d6af62937c0f4cb169 100644 GIT binary patch delta 8691 zcmb`NcYGYh700y#$3nU>4q|$p!g(Rd<^G`m!*}c1+*`3)vecXdD-?Bw;i&`Nf&tCifz zPQF^IYzn^Zg6;6qsY$qT`ir(Z3&`*G6WKm)1K4doovXbE5^v z!;9L9?zv;dTy>&?pJ_kLAbqyy6gJpiZqi{_*`-mYW^c$bNf)o0p|=4LZAtx?tbQUs zX(rL_Q|zKsohnr}s?66V=J&&_x+YbN4wDsn=h~swD~Fb^8n)LCty(k8^YttWSqJtS z8W~x=a`~E(;o}CxTl789_6*S$rnmV2wrTo& zAcWX%u{=?=t4`4?RRYgvpo@U*6!YlUicVlI=|mq)<_Z&zUC3?1?>b-}nHf5KAwFIgL)RIssE_4D}r_*SJcQ>f~ zX|V^D6ibtyy^gGjIc#3+(W5Tq=AvQsvZN=s=$l(HJ$j_+(G9(%%Pv=(a;21aJP*SR z7YMJa?*s!+KC`PL`q zo2kyXok=v^sJ|+9zz4*9>rcs;+>s#q7r%OBSCIj}qF@Lg_?JJpJtXQ0AL*9Uu$-rx%PdN&I`NM_V; z)?rW5UdT~gGCe(Ek?e&Jk?tZcnzD70t)S5v_5Ifmd!;*!E%vlUUyF1y-~Aw15f1_( z{rcdLv>+JfgMfaNML{hHl$qNLhb9FBegu!cijRNg8qo_!CZX>lkD7isDis|${rC@Xy8;Ky4II$oNAJ;M^d1w7 z-bU~qD>tJ9R*S)VT+}KWFE&};jEKr>)XHmB%IiesWEyRW&Qd8;UfF`PwRGt-uu0vl@!CD`X)P2-ZOZjy z3*a10uHFgf;$y;w%!1D}DgW7s{O3e@mxk@&0{FaA{=A6%`Ax_Nz3h`3cBvO=@x3c3 zO=#_0z=R96TVwtfJRQ%?hmgiqfjDMy$HF39Ev5oWv@NtF|eAe1FRAc5EP9vx8WEAB^J? z9EWgRisNz|>qk3*5#dkj=f_q_eh9^n3D>2j$Mr&be2q^JW#wd0_q_Rje;G0TD%8tPlHJk;vOc(N238YZbnQ)uHNaM$H z8Ms}5yn}~S)`JGzsf1*VifWNsux+}KcS#_H;?aa}36L_zy8}jC|FDyv1^4if%F@$- zdlMlQg{cMKRxwiUl)0Xjez<-|0x8s~CVV#)@_WKWexGNo6}gi6H{b_}kct}Ef*-0N zRg6E<2#uYooW$2FCj2-R@+Si1eLSSHo;KkAfRQTBRTSm61wWlGb{A#+84@w|~Lf?dkq>Nnsmw{gkkiX#} zm0f}XzfFWx^bi*O&S#{_FMfoS{JjKH=qXJ2gA_6>z%uZ#!1xH|A^na-){q$RXdsHZ1m^$ZxUv)K{DZ$5SdEfOlII!f%)$| zv%0-9;2(+1(dG-goZ$S$f`2x}%+6)`6YSvVlK;l{!D|v9i0zmO{|bCSor*1gTakf( z3qJS{?*n-=$GRp1{+sB7NT=6$|EXK>dec6@H`wg78sA{oPpkQFd>_0a@qyUf?*`#}Zwvm{ln?l*e{a9L@9p+!-2E=H(N1pw delta 9 QcmX@Mk!is@#tjPP02jstPyhe` diff --git a/llvm/lib/Analysis/models/inliner/variables/variables.data-00000-of-00002 b/llvm/lib/Analysis/models/inliner/variables/variables.data-00000-of-00002 deleted file mode 100644 index 58ebd0fc987114a4f1b631cb46adbd9641467207..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7051 zcmd6s`FGS*6vqkDa(Qj1@JcDnL>fgz5oxC_yIaAkD58|Mh+CXaLkXQ`h9oT(7u;~g zec#1>!v(>8-}mMCgTMI4cr&5&y-e=Q!E-#v({tvvnauZo?pyBtPP%*9p9}W>#YR{I zXuRI^?P1IGe5+)7B`eQn!el<(^xfPxEAJQGvG8gG9EG>;aC4=SHDH#C1v@{+QZR)x zywi5dpGUnaUO!wMunOjA&b4#>1VczRt7N0g`xjE0wm2Ac24sxqve&%mjA5L^jS3qey zgX4b>U>;Tr>N-{-y(qHSEv>2{2 zOdW=bG%XfxkbkyF#*oXTrrwvjn>sH8XX-U{i)3h8*}B`V=b?C;brGGtv9uI+ELAIvgQ!2S)eqBqneJaS)?^f zl;-xRrYmcDw5CsKj)P7UZprTwQ z&&1XAOk6|F#I@o~451lff*GngY=(A;k+qlwooLYl`a?13QoAOI*bI0p5&dlmeZPoK+C3fKQKA!OP(VKr zgDx3E0}dvlzbm1?C!&+CQiu1I=!EAK&_9Slm;9#zA10!IB%yySqLb!ThfkE~gtZmW zKaD|`Y_0*HC8B>Wp?@KwlO9=zFO}$ogAUOrUdxu?tC%DthibsriAj7TCGoA81Zi(| z_)eJwVSa<>7vl4q@L7O(m@bU`C2pj4bnKA^hfW=p2X-r@?{mH|qFCZgs zq+evjz?kln0+iBF*paKzP-|)tcVeo5jEHfW83O|gr;*7kMvVoGraXUS_X)^In3Nea zFlGj50M#=o+<48XaUh?`v_5885YQIWGIIvTtO6#589+C3m~K^8_G3`xE-6aP%!@BB zNiERVa}0@dVszmYVgO1ns}{6k00Kr34llTW4aQ+O@M+-&21e#mhQ&;9vHsoMO)Ho< cwleWgPGl6FT)@Z%!ki4@zZ<$$O5JY*0Kd;lC;$Ke delta 310 zcmey#^p8p481sh+1_m|`CMhNkMg|$4i2@4T8r|lm36CnLGw4W6v{$NUby^VS=o9M7 z!6?Kb#KfTl#3>St3LF{>vP|1OczFe6L=E-z9795aJe|VK85mf2jZIc$X-r@?{mH|q zFCZgnRA$1!m>rV>)TjZ}xFc7iq1MzQ?!;6988Kshy}BF*1`S3Ni&u;q3m8p#{>bhV zkdZRcFEV9d%#F|xs%PS00_wW)no;8blWBd-vLK*^re&54jJFs~V`jW#)Zj4Ps;unC zpvqfPl$eW k;9~r@zh|#y;@HK+4-x``$q|f_Tnr51zZ<$$O5JY*02b0nP5=M^ From 87f8a4f9a2314044bf007e0d4564a40386751842 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 12 Jul 2020 17:22:15 -0400 Subject: [PATCH 127/771] AMDGPU/GlobalISel: Add tests for 96-bit add/sub/mul I almost regressed these, so add tests for them. --- .../AMDGPU/GlobalISel/legalize-add.mir | 42 +++++++++ .../AMDGPU/GlobalISel/legalize-mul.mir | 90 +++++++++++++++++++ .../AMDGPU/GlobalISel/legalize-sub.mir | 42 +++++++++ 3 files changed, 174 insertions(+) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir index 42a3f0547343d..175144958cd99 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-add.mir @@ -507,3 +507,45 @@ body: | # %5:_(s64) = G_ANYEXT %4 # $vgpr0_vgpr1 = COPY %5 # ... + +--- +name: test_add_s96 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2, $vgpr3_vgpr4_vgpr5 + + ; GFX6-LABEL: name: test_add_s96 + ; GFX6: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX6: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX6: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX6: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX6: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV]], [[UV3]] + ; GFX6: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV1]], [[UV4]], [[UADDO1]] + ; GFX6: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV2]], [[UV5]], [[UADDE1]] + ; GFX6: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32), [[UADDE2]](s32) + ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + ; GFX8-LABEL: name: test_add_s96 + ; GFX8: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX8: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX8: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX8: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX8: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV]], [[UV3]] + ; GFX8: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV1]], [[UV4]], [[UADDO1]] + ; GFX8: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV2]], [[UV5]], [[UADDE1]] + ; GFX8: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32), [[UADDE2]](s32) + ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + ; GFX9-LABEL: name: test_add_s96 + ; GFX9: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX9: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX9: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[UV]], [[UV3]] + ; GFX9: [[UADDE:%[0-9]+]]:_(s32), [[UADDE1:%[0-9]+]]:_(s1) = G_UADDE [[UV1]], [[UV4]], [[UADDO1]] + ; GFX9: [[UADDE2:%[0-9]+]]:_(s32), [[UADDE3:%[0-9]+]]:_(s1) = G_UADDE [[UV2]], [[UV5]], [[UADDE1]] + ; GFX9: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[UADDO]](s32), [[UADDE]](s32), [[UADDE2]](s32) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + %0:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + %2:_(s96) = G_ADD %0, %1 + $vgpr0_vgpr1_vgpr2 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-mul.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-mul.mir index a1499050f831c..63db6ec0d0b34 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-mul.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-mul.mir @@ -561,3 +561,93 @@ body: | # %5:_(s64) = G_ANYEXT %4 # $vgpr0_vgpr1 = COPY %5 # ... + +--- +name: test_mul_s96 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2, $vgpr3_vgpr4_vgpr5 + + ; GFX6-LABEL: name: test_mul_s96 + ; GFX6: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX6: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX6: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX6: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX6: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV3]] + ; GFX6: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[UV1]], [[UV3]] + ; GFX6: [[MUL2:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV4]] + ; GFX6: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH [[UV]], [[UV3]] + ; GFX6: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[MUL1]], [[MUL2]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO1]](s1) + ; GFX6: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UADDO]], [[UMULH]] + ; GFX6: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO3]](s1) + ; GFX6: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ZEXT]], [[ZEXT1]] + ; GFX6: [[MUL3:%[0-9]+]]:_(s32) = G_MUL [[UV2]], [[UV3]] + ; GFX6: [[MUL4:%[0-9]+]]:_(s32) = G_MUL [[UV1]], [[UV4]] + ; GFX6: [[MUL5:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV5]] + ; GFX6: [[UMULH1:%[0-9]+]]:_(s32) = G_UMULH [[UV1]], [[UV3]] + ; GFX6: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH [[UV]], [[UV4]] + ; GFX6: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[MUL3]], [[MUL4]] + ; GFX6: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[MUL5]] + ; GFX6: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[ADD2]], [[UMULH1]] + ; GFX6: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[UMULH2]] + ; GFX6: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[ADD]] + ; GFX6: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[MUL]](s32), [[UADDO2]](s32), [[ADD5]](s32) + ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + ; GFX8-LABEL: name: test_mul_s96 + ; GFX8: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX8: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX8: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX8: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX8: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV3]] + ; GFX8: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[UV1]], [[UV3]] + ; GFX8: [[MUL2:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV4]] + ; GFX8: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH [[UV]], [[UV3]] + ; GFX8: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[MUL1]], [[MUL2]] + ; GFX8: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO1]](s1) + ; GFX8: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UADDO]], [[UMULH]] + ; GFX8: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO3]](s1) + ; GFX8: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ZEXT]], [[ZEXT1]] + ; GFX8: [[MUL3:%[0-9]+]]:_(s32) = G_MUL [[UV2]], [[UV3]] + ; GFX8: [[MUL4:%[0-9]+]]:_(s32) = G_MUL [[UV1]], [[UV4]] + ; GFX8: [[MUL5:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV5]] + ; GFX8: [[UMULH1:%[0-9]+]]:_(s32) = G_UMULH [[UV1]], [[UV3]] + ; GFX8: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH [[UV]], [[UV4]] + ; GFX8: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[MUL3]], [[MUL4]] + ; GFX8: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[MUL5]] + ; GFX8: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[ADD2]], [[UMULH1]] + ; GFX8: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[UMULH2]] + ; GFX8: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[ADD]] + ; GFX8: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[MUL]](s32), [[UADDO2]](s32), [[ADD5]](s32) + ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + ; GFX9-LABEL: name: test_mul_s96 + ; GFX9: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX9: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX9: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV3]] + ; GFX9: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[UV1]], [[UV3]] + ; GFX9: [[MUL2:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV4]] + ; GFX9: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH [[UV]], [[UV3]] + ; GFX9: [[UADDO:%[0-9]+]]:_(s32), [[UADDO1:%[0-9]+]]:_(s1) = G_UADDO [[MUL1]], [[MUL2]] + ; GFX9: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO1]](s1) + ; GFX9: [[UADDO2:%[0-9]+]]:_(s32), [[UADDO3:%[0-9]+]]:_(s1) = G_UADDO [[UADDO]], [[UMULH]] + ; GFX9: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UADDO3]](s1) + ; GFX9: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ZEXT]], [[ZEXT1]] + ; GFX9: [[MUL3:%[0-9]+]]:_(s32) = G_MUL [[UV2]], [[UV3]] + ; GFX9: [[MUL4:%[0-9]+]]:_(s32) = G_MUL [[UV1]], [[UV4]] + ; GFX9: [[MUL5:%[0-9]+]]:_(s32) = G_MUL [[UV]], [[UV5]] + ; GFX9: [[UMULH1:%[0-9]+]]:_(s32) = G_UMULH [[UV1]], [[UV3]] + ; GFX9: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH [[UV]], [[UV4]] + ; GFX9: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[MUL3]], [[MUL4]] + ; GFX9: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ADD1]], [[MUL5]] + ; GFX9: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[ADD2]], [[UMULH1]] + ; GFX9: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[ADD3]], [[UMULH2]] + ; GFX9: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[ADD4]], [[ADD]] + ; GFX9: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[MUL]](s32), [[UADDO2]](s32), [[ADD5]](s32) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + %0:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + %2:_(s96) = G_MUL %0, %1 + $vgpr0_vgpr1_vgpr2 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sub.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sub.mir index 8cb346a761882..3fb34a4edc923 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sub.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-sub.mir @@ -501,3 +501,45 @@ body: | # %5:_(s64) = G_ANYEXT %4 # $vgpr0_vgpr1 = COPY %5 # ... + +--- +name: test_sub_s96 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2, $vgpr3_vgpr4_vgpr5 + + ; GFX6-LABEL: name: test_sub_s96 + ; GFX6: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX6: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX6: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX6: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX6: [[USUBO:%[0-9]+]]:_(s32), [[USUBO1:%[0-9]+]]:_(s1) = G_USUBO [[UV]], [[UV3]] + ; GFX6: [[USUBE:%[0-9]+]]:_(s32), [[USUBE1:%[0-9]+]]:_(s1) = G_USUBE [[UV1]], [[UV4]], [[USUBO1]] + ; GFX6: [[USUBE2:%[0-9]+]]:_(s32), [[USUBE3:%[0-9]+]]:_(s1) = G_USUBE [[UV2]], [[UV5]], [[USUBE1]] + ; GFX6: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBO]](s32), [[USUBE]](s32), [[USUBE2]](s32) + ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + ; GFX8-LABEL: name: test_sub_s96 + ; GFX8: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX8: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX8: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX8: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX8: [[USUBO:%[0-9]+]]:_(s32), [[USUBO1:%[0-9]+]]:_(s1) = G_USUBO [[UV]], [[UV3]] + ; GFX8: [[USUBE:%[0-9]+]]:_(s32), [[USUBE1:%[0-9]+]]:_(s1) = G_USUBE [[UV1]], [[UV4]], [[USUBO1]] + ; GFX8: [[USUBE2:%[0-9]+]]:_(s32), [[USUBE3:%[0-9]+]]:_(s1) = G_USUBE [[UV2]], [[UV5]], [[USUBE1]] + ; GFX8: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBO]](s32), [[USUBE]](s32), [[USUBE2]](s32) + ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + ; GFX9-LABEL: name: test_sub_s96 + ; GFX9: [[COPY:%[0-9]+]]:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[COPY1:%[0-9]+]]:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32), [[UV2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](s96) + ; GFX9: [[UV3:%[0-9]+]]:_(s32), [[UV4:%[0-9]+]]:_(s32), [[UV5:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](s96) + ; GFX9: [[USUBO:%[0-9]+]]:_(s32), [[USUBO1:%[0-9]+]]:_(s1) = G_USUBO [[UV]], [[UV3]] + ; GFX9: [[USUBE:%[0-9]+]]:_(s32), [[USUBE1:%[0-9]+]]:_(s1) = G_USUBE [[UV1]], [[UV4]], [[USUBO1]] + ; GFX9: [[USUBE2:%[0-9]+]]:_(s32), [[USUBE3:%[0-9]+]]:_(s1) = G_USUBE [[UV2]], [[UV5]], [[USUBE1]] + ; GFX9: [[MV:%[0-9]+]]:_(s96) = G_MERGE_VALUES [[USUBO]](s32), [[USUBE]](s32), [[USUBE2]](s32) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[MV]](s96) + %0:_(s96) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(s96) = COPY $vgpr3_vgpr4_vgpr5 + %2:_(s96) = G_SUB %0, %1 + $vgpr0_vgpr1_vgpr2 = COPY %2 +... From fdb69539bcd250f6e4f49197c9b8149a7542e3ff Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Wed, 8 Jul 2020 15:16:21 -0700 Subject: [PATCH 128/771] [AST] Fix potential nullptr dereference in Expr::HasSideEffects Array returned by LambdaExpr::capture_inits() can contain nullptrs. Differential Revision: https://reviews.llvm.org/D83438 --- clang/include/clang/AST/ExprCXX.h | 1 + clang/lib/AST/Expr.cpp | 2 +- clang/unittests/AST/CMakeLists.txt | 1 + clang/unittests/AST/HasSideEffectsTest.cpp | 86 ++++++++++++++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 clang/unittests/AST/HasSideEffectsTest.cpp diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 178f4db770618..6f0b68479b9d7 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1931,6 +1931,7 @@ class LambdaExpr final : public Expr, /// Const iterator that walks over the capture initialization /// arguments. + /// FIXME: This interface is prone to being used incorrectly. using const_capture_init_iterator = Expr *const *; /// Retrieve the initialization expressions for this lambda's captures. diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 343a271c33944..399e7e13c4459 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3629,7 +3629,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case LambdaExprClass: { const LambdaExpr *LE = cast(this); for (Expr *E : LE->capture_inits()) - if (E->HasSideEffects(Ctx, IncludePossibleEffects)) + if (E && E->HasSideEffects(Ctx, IncludePossibleEffects)) return true; return false; } diff --git a/clang/unittests/AST/CMakeLists.txt b/clang/unittests/AST/CMakeLists.txt index 2e750ac9ea925..185995d5b5a27 100644 --- a/clang/unittests/AST/CMakeLists.txt +++ b/clang/unittests/AST/CMakeLists.txt @@ -26,6 +26,7 @@ add_clang_unittest(ASTTests DeclTest.cpp EvaluateAsRValueTest.cpp ExternalASTSourceTest.cpp + HasSideEffectsTest.cpp NamedDeclPrinterTest.cpp RecursiveASTVisitorTest.cpp SizelessTypesTest.cpp diff --git a/clang/unittests/AST/HasSideEffectsTest.cpp b/clang/unittests/AST/HasSideEffectsTest.cpp new file mode 100644 index 0000000000000..842afd8d7a9c3 --- /dev/null +++ b/clang/unittests/AST/HasSideEffectsTest.cpp @@ -0,0 +1,86 @@ +//===- unittest/AST/HasSideEffectsTest.cpp --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/Frontend/FrontendAction.h" +#include "clang/Tooling/Tooling.h" +#include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/STLExtras.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include + +using namespace clang; + +namespace { +class ProcessASTAction : public clang::ASTFrontendAction { +public: + ProcessASTAction(llvm::unique_function Process) + : Process(std::move(Process)) { + assert(this->Process); + } + + std::unique_ptr CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + class Consumer : public ASTConsumer { + public: + Consumer(llvm::function_ref Process) + : Process(Process) {} + + void HandleTranslationUnit(ASTContext &Ctx) override { Process(Ctx); } + + private: + llvm::function_ref Process; + }; + + return std::make_unique(Process); + } + +private: + llvm::unique_function Process; +}; + +class RunHasSideEffects + : public RecursiveASTVisitor { +public: + RunHasSideEffects(ASTContext& Ctx) + : Ctx(Ctx) {} + + bool VisitLambdaExpr(LambdaExpr *LE) { + LE->HasSideEffects(Ctx); + return true; + } + + ASTContext& Ctx; +}; +} // namespace + +TEST(HasSideEffectsTest, All) { + llvm::StringRef Code = R"cpp( +void Test() { + int msize = 4; + float arr[msize]; + [&arr] {}; +} + )cpp"; + + ASSERT_NO_FATAL_FAILURE( + clang::tooling::runToolOnCode( + std::make_unique( + [&](clang::ASTContext &Ctx) { + RunHasSideEffects Visitor(Ctx); + Visitor.TraverseAST(Ctx); + } + ), + Code) + ); + +} From c1efd6675a901e8c0033026752c05396a3b26fec Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 13 Jul 2020 18:10:37 +0000 Subject: [PATCH 129/771] [gn build] Port fdb69539bcd --- llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn index f25ead00165c0..e8050f469f046 100644 --- a/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/unittests/AST/BUILD.gn @@ -31,6 +31,7 @@ unittest("ASTTests") { "DeclTest.cpp", "EvaluateAsRValueTest.cpp", "ExternalASTSourceTest.cpp", + "HasSideEffectsTest.cpp", "NamedDeclPrinterTest.cpp", "RecursiveASTVisitorTest.cpp", "SizelessTypesTest.cpp", From fefe7555e97685d61f76d4e7dfcabb163ff9bcdf Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Mon, 13 Jul 2020 11:10:56 -0700 Subject: [PATCH 130/771] [NewPM][opt] Translate -foo-analysis to require Fixes 53 check-llvm tests under NPM. Reviewed By: asbirlea Differential Revision: https://reviews.llvm.org/D83633 --- llvm/include/llvm/Passes/PassBuilder.h | 3 +++ llvm/lib/Passes/PassBuilder.cpp | 17 +++++++++++++++++ llvm/tools/opt/NewPMDriver.cpp | 7 +++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index f9b0d939e5f8c..0357e4a2fc058 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -518,6 +518,9 @@ class PassBuilder { /// Returns true if the pass name is the name of an alias analysis pass. bool isAAPassName(StringRef PassName); + /// Returns true if the pass name is the name of a (non-alias) analysis pass. + bool isAnalysisPassName(StringRef PassName); + /// Register a callback for a default optimizer pipeline extension /// point /// diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 7f57634676956..537d300fee557 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -2666,3 +2666,20 @@ bool PassBuilder::isAAPassName(StringRef PassName) { #include "PassRegistry.def" return false; } + +bool PassBuilder::isAnalysisPassName(StringRef PassName) { +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + if (PassName == NAME) \ + return true; +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + if (PassName == NAME) \ + return true; +#define LOOP_ANALYSIS(NAME, CREATE_PASS) \ + if (PassName == NAME) \ + return true; +#define CGSSC_ANALYSIS(NAME, CREATE_PASS) \ + if (PassName == NAME) \ + return true; +#include "PassRegistry.def" + return false; +} diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp index 8f8ca352dcfff..b94c58decdda2 100644 --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -358,8 +358,11 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, } } for (auto PassName : NonAAPasses) { - if (auto Err = - PB.parsePassPipeline(MPM, PassName, VerifyEachPass, DebugPM)) { + std::string ModifiedPassName(PassName.begin(), PassName.end()); + if (PB.isAnalysisPassName(PassName)) + ModifiedPassName = "require<" + ModifiedPassName + ">"; + if (auto Err = PB.parsePassPipeline(MPM, ModifiedPassName, VerifyEachPass, + DebugPM)) { errs() << Arg0 << ": " << toString(std::move(Err)) << "\n"; return false; } From 62881fda5852b9a5960c3f8c26e864d5085d11bb Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Thu, 9 Jul 2020 09:56:26 +0200 Subject: [PATCH 131/771] Fix HexagonGenExtract return status Differential Revision: https://reviews.llvm.org/D83460 --- llvm/lib/Target/Hexagon/HexagonGenExtract.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/Hexagon/HexagonGenExtract.cpp b/llvm/lib/Target/Hexagon/HexagonGenExtract.cpp index 342ca21525c5e..d9307190ae169 100644 --- a/llvm/lib/Target/Hexagon/HexagonGenExtract.cpp +++ b/llvm/lib/Target/Hexagon/HexagonGenExtract.cpp @@ -221,15 +221,16 @@ bool HexagonGenExtract::convert(Instruction *In) { } bool HexagonGenExtract::visitBlock(BasicBlock *B) { + bool Changed = false; + // Depth-first, bottom-up traversal. for (auto *DTN : children(DT->getNode(B))) - visitBlock(DTN->getBlock()); + Changed |= visitBlock(DTN->getBlock()); // Allow limiting the number of generated extracts for debugging purposes. bool HasCutoff = ExtractCutoff.getPosition(); unsigned Cutoff = ExtractCutoff; - bool Changed = false; BasicBlock::iterator I = std::prev(B->end()), NextI, Begin = B->begin(); while (true) { if (HasCutoff && (ExtractCount >= Cutoff)) From 9cafbf8f66c9596d8b31293830d8892db0837745 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Mon, 13 Jul 2020 14:40:04 -0400 Subject: [PATCH 132/771] [NFC] Remove unused header include Differential Revision: https://reviews.llvm.org/D83706 --- llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h index a41d4b0777f82..9f2cdf0292a73 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h @@ -23,7 +23,6 @@ #include "llvm/Support/MathExtras.h" #include #include -#include namespace llvm { namespace orc { From 9d3e9a3e3c10cf7ff961df8e107c7cb0e1bc447c Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Mon, 13 Jul 2020 20:44:03 +0200 Subject: [PATCH 133/771] [clangd] Remove const_cast. NFC --- clang-tools-extra/clangd/CompileCommands.cpp | 3 +-- clang-tools-extra/clangd/Config.h | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index 0b27e0e3e8284..4b69555769423 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -183,8 +183,7 @@ CommandMangler CommandMangler::forTests() { } void CommandMangler::adjust(std::vector &Cmd) const { - // FIXME: remove const_cast once unique_function is const-compatible. - for (auto &Edit : const_cast(Config::current()).CompileFlags.Edits) + for (auto &Edit : Config::current().CompileFlags.Edits) Edit(Cmd); // Check whether the flag exists, either as -flag or -flag=* diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h index 878c9e8549b52..d2c3ef37abd5c 100644 --- a/clang-tools-extra/clangd/Config.h +++ b/clang-tools-extra/clangd/Config.h @@ -52,8 +52,8 @@ struct Config { /// Controls how the compile command for the current file is determined. struct { // Edits to apply to the compile command, in sequence. - // FIXME: these functions need to be const-callable. For now, const_cast. - std::vector &)>> Edits; + std::vector &) const>> + Edits; } CompileFlags; }; From c0ee2d74680cc89ca6301613f1268de47e3d3bfc Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 12 Jul 2020 12:49:04 -0400 Subject: [PATCH 134/771] AMDGPU/GlobalISel: Add baseline add/sub sat legalization tests --- .../AMDGPU/GlobalISel/legalize-saddsat.mir | 375 ++++++++++++++++++ .../AMDGPU/GlobalISel/legalize-ssubsat.mir | 375 ++++++++++++++++++ .../AMDGPU/GlobalISel/legalize-uaddsat.mir | 375 ++++++++++++++++++ .../AMDGPU/GlobalISel/legalize-usubsat.mir | 375 ++++++++++++++++++ 4 files changed, 1500 insertions(+) create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir new file mode 100644 index 0000000000000..250645202af5a --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir @@ -0,0 +1,375 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=tahiti -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX6 %s +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=fiji -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX8 %s +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s + +--- +name: saddsat_s7 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: saddsat_s7 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s7) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s7) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: saddsat_s7 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s7) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s7) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: saddsat_s7 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s7) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s7) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s7) = G_TRUNC %0 + %3:_(s7) = G_TRUNC %1 + %4:_(s7) = G_SADDSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: saddsat_s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: saddsat_s8 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s8) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: saddsat_s8 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s8) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: saddsat_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s8) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s8) = G_TRUNC %0 + %3:_(s8) = G_TRUNC %1 + %4:_(s8) = G_SADDSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: saddsat_v2s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: saddsat_v2s8 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX6: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(<2 x s8>) = G_SADDSAT [[BITCAST]], [[BITCAST1]] + ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SADDSAT]](<2 x s8>) + ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: saddsat_v2s8 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX8: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(<2 x s8>) = G_SADDSAT [[BITCAST]], [[BITCAST1]] + ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SADDSAT]](<2 x s8>) + ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: saddsat_v2s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX9: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(<2 x s8>) = G_SADDSAT [[BITCAST]], [[BITCAST1]] + ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SADDSAT]](<2 x s8>) + ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(<2 x s8>) = G_BITCAST %2 + %5:_(<2 x s8>) = G_BITCAST %3 + %6:_(<2 x s8>) = G_SADDSAT %4, %5 + %7:_(s16) = G_BITCAST %6 + %8:_(s32) = G_ANYEXT %7 + $vgpr0 = COPY %8 +... + +--- +name: saddsat_s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: saddsat_s16 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: saddsat_s16 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: saddsat_s16 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(s16) = G_SADDSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: saddsat_v2s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: saddsat_v2s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX6: [[SADDSAT:%[0-9]+]]:_(<2 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0 = COPY [[SADDSAT]](<2 x s16>) + ; GFX8-LABEL: name: saddsat_v2s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX8: [[SADDSAT:%[0-9]+]]:_(<2 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0 = COPY [[SADDSAT]](<2 x s16>) + ; GFX9-LABEL: name: saddsat_v2s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX9: [[SADDSAT:%[0-9]+]]:_(<2 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[SADDSAT]](<2 x s16>) + %0:_(<2 x s16>) = COPY $vgpr0 + %1:_(<2 x s16>) = COPY $vgpr1 + %2:_(<2 x s16>) = G_SADDSAT %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: saddsat_v3s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2 + + ; GFX6-LABEL: name: saddsat_v3s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX6: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(<3 x s16>) = G_SADDSAT [[UV]], [[UV1]] + ; GFX6: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX6: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + ; GFX8-LABEL: name: saddsat_v3s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX8: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(<3 x s16>) = G_SADDSAT [[UV]], [[UV1]] + ; GFX8: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX8: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + ; GFX9-LABEL: name: saddsat_v3s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(<3 x s16>) = G_SADDSAT [[UV]], [[UV1]] + ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + %0:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(<3 x s16>), %2:_(<3 x s16>) = G_UNMERGE_VALUES %0 + %3:_(<3 x s16>) = G_SADDSAT %1, %2 + %4:_(<3 x s16>) = G_IMPLICIT_DEF + %5:_(<6 x s16>) = G_CONCAT_VECTORS %3, %4 + $vgpr0_vgpr1_vgpr2 = COPY %5 +... + +--- +name: saddsat_v4s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: saddsat_v4s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX6: [[SADDSAT:%[0-9]+]]:_(<4 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[SADDSAT]](<4 x s16>) + ; GFX8-LABEL: name: saddsat_v4s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX8: [[SADDSAT:%[0-9]+]]:_(<4 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[SADDSAT]](<4 x s16>) + ; GFX9-LABEL: name: saddsat_v4s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX9: [[SADDSAT:%[0-9]+]]:_(<4 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[SADDSAT]](<4 x s16>) + %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 + %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 + %2:_(<4 x s16>) = G_SADDSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: saddsat_s32 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: saddsat_s32 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s32) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0 = COPY [[SADDSAT]](s32) + ; GFX8-LABEL: name: saddsat_s32 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s32) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0 = COPY [[SADDSAT]](s32) + ; GFX9-LABEL: name: saddsat_s32 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s32) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[SADDSAT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_SADDSAT %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: saddsat_v2s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: saddsat_v2s32 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX6: [[SADDSAT:%[0-9]+]]:_(<2 x s32>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[SADDSAT]](<2 x s32>) + ; GFX8-LABEL: name: saddsat_v2s32 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX8: [[SADDSAT:%[0-9]+]]:_(<2 x s32>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[SADDSAT]](<2 x s32>) + ; GFX9-LABEL: name: saddsat_v2s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX9: [[SADDSAT:%[0-9]+]]:_(<2 x s32>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[SADDSAT]](<2 x s32>) + %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 + %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 + %2:_(<2 x s32>) = G_SADDSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: saddsat_s64 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: saddsat_s64 + ; GFX6: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s64) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[SADDSAT]](s64) + ; GFX8-LABEL: name: saddsat_s64 + ; GFX8: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s64) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[SADDSAT]](s64) + ; GFX9-LABEL: name: saddsat_s64 + ; GFX9: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s64) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[SADDSAT]](s64) + %0:_(s64) = COPY $vgpr0_vgpr1 + %1:_(s64) = COPY $vgpr2_vgpr3 + %2:_(s64) = G_SADDSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: saddsat_v2s64 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7 + + ; GFX6-LABEL: name: saddsat_v2s64 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX6: [[SADDSAT:%[0-9]+]]:_(<2 x s64>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SADDSAT]](<2 x s64>) + ; GFX8-LABEL: name: saddsat_v2s64 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX8: [[SADDSAT:%[0-9]+]]:_(<2 x s64>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SADDSAT]](<2 x s64>) + ; GFX9-LABEL: name: saddsat_v2s64 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX9: [[SADDSAT:%[0-9]+]]:_(<2 x s64>) = G_SADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SADDSAT]](<2 x s64>) + %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + %1:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + %2:_(<2 x s64>) = G_SADDSAT %0, %1 + $vgpr0_vgpr1_vgpr2_vgpr3 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir new file mode 100644 index 0000000000000..53c9ba8410c72 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir @@ -0,0 +1,375 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=tahiti -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX6 %s +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=fiji -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX8 %s +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s + +--- +name: ssubsat_s7 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: ssubsat_s7 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s7) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s7) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: ssubsat_s7 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s7) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s7) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: ssubsat_s7 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s7) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s7) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s7) = G_TRUNC %0 + %3:_(s7) = G_TRUNC %1 + %4:_(s7) = G_SSUBSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: ssubsat_s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: ssubsat_s8 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s8) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: ssubsat_s8 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s8) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: ssubsat_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s8) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s8) = G_TRUNC %0 + %3:_(s8) = G_TRUNC %1 + %4:_(s8) = G_SSUBSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: ssubsat_v2s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: ssubsat_v2s8 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX6: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<2 x s8>) = G_SSUBSAT [[BITCAST]], [[BITCAST1]] + ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SSUBSAT]](<2 x s8>) + ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: ssubsat_v2s8 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX8: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<2 x s8>) = G_SSUBSAT [[BITCAST]], [[BITCAST1]] + ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SSUBSAT]](<2 x s8>) + ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: ssubsat_v2s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX9: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<2 x s8>) = G_SSUBSAT [[BITCAST]], [[BITCAST1]] + ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SSUBSAT]](<2 x s8>) + ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(<2 x s8>) = G_BITCAST %2 + %5:_(<2 x s8>) = G_BITCAST %3 + %6:_(<2 x s8>) = G_SSUBSAT %4, %5 + %7:_(s16) = G_BITCAST %6 + %8:_(s32) = G_ANYEXT %7 + $vgpr0 = COPY %8 +... + +--- +name: ssubsat_s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: ssubsat_s16 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: ssubsat_s16 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: ssubsat_s16 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(s16) = G_SSUBSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: ssubsat_v2s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: ssubsat_v2s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<2 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0 = COPY [[SSUBSAT]](<2 x s16>) + ; GFX8-LABEL: name: ssubsat_v2s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<2 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0 = COPY [[SSUBSAT]](<2 x s16>) + ; GFX9-LABEL: name: ssubsat_v2s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<2 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[SSUBSAT]](<2 x s16>) + %0:_(<2 x s16>) = COPY $vgpr0 + %1:_(<2 x s16>) = COPY $vgpr1 + %2:_(<2 x s16>) = G_SSUBSAT %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: ssubsat_v3s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2 + + ; GFX6-LABEL: name: ssubsat_v3s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX6: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<3 x s16>) = G_SSUBSAT [[UV]], [[UV1]] + ; GFX6: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX6: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SSUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + ; GFX8-LABEL: name: ssubsat_v3s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX8: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<3 x s16>) = G_SSUBSAT [[UV]], [[UV1]] + ; GFX8: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX8: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SSUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + ; GFX9-LABEL: name: ssubsat_v3s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<3 x s16>) = G_SSUBSAT [[UV]], [[UV1]] + ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SSUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + %0:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(<3 x s16>), %2:_(<3 x s16>) = G_UNMERGE_VALUES %0 + %3:_(<3 x s16>) = G_SSUBSAT %1, %2 + %4:_(<3 x s16>) = G_IMPLICIT_DEF + %5:_(<6 x s16>) = G_CONCAT_VECTORS %3, %4 + $vgpr0_vgpr1_vgpr2 = COPY %5 +... + +--- +name: ssubsat_v4s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: ssubsat_v4s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<4 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<4 x s16>) + ; GFX8-LABEL: name: ssubsat_v4s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<4 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<4 x s16>) + ; GFX9-LABEL: name: ssubsat_v4s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<4 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<4 x s16>) + %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 + %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 + %2:_(<4 x s16>) = G_SSUBSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: ssubsat_s32 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: ssubsat_s32 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s32) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0 = COPY [[SSUBSAT]](s32) + ; GFX8-LABEL: name: ssubsat_s32 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s32) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0 = COPY [[SSUBSAT]](s32) + ; GFX9-LABEL: name: ssubsat_s32 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s32) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[SSUBSAT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_SSUBSAT %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: ssubsat_v2s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: ssubsat_v2s32 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<2 x s32>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<2 x s32>) + ; GFX8-LABEL: name: ssubsat_v2s32 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<2 x s32>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<2 x s32>) + ; GFX9-LABEL: name: ssubsat_v2s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<2 x s32>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<2 x s32>) + %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 + %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 + %2:_(<2 x s32>) = G_SSUBSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: ssubsat_s64 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: ssubsat_s64 + ; GFX6: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s64) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[SSUBSAT]](s64) + ; GFX8-LABEL: name: ssubsat_s64 + ; GFX8: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s64) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[SSUBSAT]](s64) + ; GFX9-LABEL: name: ssubsat_s64 + ; GFX9: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s64) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[SSUBSAT]](s64) + %0:_(s64) = COPY $vgpr0_vgpr1 + %1:_(s64) = COPY $vgpr2_vgpr3 + %2:_(s64) = G_SSUBSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: ssubsat_v2s64 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7 + + ; GFX6-LABEL: name: ssubsat_v2s64 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<2 x s64>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SSUBSAT]](<2 x s64>) + ; GFX8-LABEL: name: ssubsat_v2s64 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<2 x s64>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SSUBSAT]](<2 x s64>) + ; GFX9-LABEL: name: ssubsat_v2s64 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<2 x s64>) = G_SSUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SSUBSAT]](<2 x s64>) + %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + %1:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + %2:_(<2 x s64>) = G_SSUBSAT %0, %1 + $vgpr0_vgpr1_vgpr2_vgpr3 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir new file mode 100644 index 0000000000000..79d671214b549 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir @@ -0,0 +1,375 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=tahiti -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX6 %s +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=fiji -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX8 %s +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s + +--- +name: uaddsat_s7 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: uaddsat_s7 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s7) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s7) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: uaddsat_s7 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s7) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s7) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: uaddsat_s7 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s7) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s7) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s7) = G_TRUNC %0 + %3:_(s7) = G_TRUNC %1 + %4:_(s7) = G_UADDSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: uaddsat_s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: uaddsat_s8 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s8) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: uaddsat_s8 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s8) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: uaddsat_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s8) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s8) = G_TRUNC %0 + %3:_(s8) = G_TRUNC %1 + %4:_(s8) = G_UADDSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: uaddsat_v2s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: uaddsat_v2s8 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX6: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(<2 x s8>) = G_UADDSAT [[BITCAST]], [[BITCAST1]] + ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[UADDSAT]](<2 x s8>) + ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: uaddsat_v2s8 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX8: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(<2 x s8>) = G_UADDSAT [[BITCAST]], [[BITCAST1]] + ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[UADDSAT]](<2 x s8>) + ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: uaddsat_v2s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX9: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(<2 x s8>) = G_UADDSAT [[BITCAST]], [[BITCAST1]] + ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[UADDSAT]](<2 x s8>) + ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(<2 x s8>) = G_BITCAST %2 + %5:_(<2 x s8>) = G_BITCAST %3 + %6:_(<2 x s8>) = G_UADDSAT %4, %5 + %7:_(s16) = G_BITCAST %6 + %8:_(s32) = G_ANYEXT %7 + $vgpr0 = COPY %8 +... + +--- +name: uaddsat_s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: uaddsat_s16 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: uaddsat_s16 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: uaddsat_s16 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(s16) = G_UADDSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: uaddsat_v2s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: uaddsat_v2s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX6: [[UADDSAT:%[0-9]+]]:_(<2 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0 = COPY [[UADDSAT]](<2 x s16>) + ; GFX8-LABEL: name: uaddsat_v2s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX8: [[UADDSAT:%[0-9]+]]:_(<2 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0 = COPY [[UADDSAT]](<2 x s16>) + ; GFX9-LABEL: name: uaddsat_v2s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX9: [[UADDSAT:%[0-9]+]]:_(<2 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[UADDSAT]](<2 x s16>) + %0:_(<2 x s16>) = COPY $vgpr0 + %1:_(<2 x s16>) = COPY $vgpr1 + %2:_(<2 x s16>) = G_UADDSAT %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: uaddsat_v3s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2 + + ; GFX6-LABEL: name: uaddsat_v3s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX6: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(<3 x s16>) = G_UADDSAT [[UV]], [[UV1]] + ; GFX6: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX6: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[UADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + ; GFX8-LABEL: name: uaddsat_v3s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX8: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(<3 x s16>) = G_UADDSAT [[UV]], [[UV1]] + ; GFX8: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX8: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[UADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + ; GFX9-LABEL: name: uaddsat_v3s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(<3 x s16>) = G_UADDSAT [[UV]], [[UV1]] + ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[UADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + %0:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(<3 x s16>), %2:_(<3 x s16>) = G_UNMERGE_VALUES %0 + %3:_(<3 x s16>) = G_UADDSAT %1, %2 + %4:_(<3 x s16>) = G_IMPLICIT_DEF + %5:_(<6 x s16>) = G_CONCAT_VECTORS %3, %4 + $vgpr0_vgpr1_vgpr2 = COPY %5 +... + +--- +name: uaddsat_v4s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: uaddsat_v4s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX6: [[UADDSAT:%[0-9]+]]:_(<4 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[UADDSAT]](<4 x s16>) + ; GFX8-LABEL: name: uaddsat_v4s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX8: [[UADDSAT:%[0-9]+]]:_(<4 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[UADDSAT]](<4 x s16>) + ; GFX9-LABEL: name: uaddsat_v4s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UADDSAT:%[0-9]+]]:_(<4 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[UADDSAT]](<4 x s16>) + %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 + %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 + %2:_(<4 x s16>) = G_UADDSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: uaddsat_s32 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: uaddsat_s32 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s32) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0 = COPY [[UADDSAT]](s32) + ; GFX8-LABEL: name: uaddsat_s32 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s32) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0 = COPY [[UADDSAT]](s32) + ; GFX9-LABEL: name: uaddsat_s32 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s32) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[UADDSAT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_UADDSAT %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: uaddsat_v2s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: uaddsat_v2s32 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX6: [[UADDSAT:%[0-9]+]]:_(<2 x s32>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[UADDSAT]](<2 x s32>) + ; GFX8-LABEL: name: uaddsat_v2s32 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX8: [[UADDSAT:%[0-9]+]]:_(<2 x s32>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[UADDSAT]](<2 x s32>) + ; GFX9-LABEL: name: uaddsat_v2s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX9: [[UADDSAT:%[0-9]+]]:_(<2 x s32>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[UADDSAT]](<2 x s32>) + %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 + %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 + %2:_(<2 x s32>) = G_UADDSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: uaddsat_s64 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: uaddsat_s64 + ; GFX6: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s64) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[UADDSAT]](s64) + ; GFX8-LABEL: name: uaddsat_s64 + ; GFX8: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s64) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[UADDSAT]](s64) + ; GFX9-LABEL: name: uaddsat_s64 + ; GFX9: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s64) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[UADDSAT]](s64) + %0:_(s64) = COPY $vgpr0_vgpr1 + %1:_(s64) = COPY $vgpr2_vgpr3 + %2:_(s64) = G_UADDSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: uaddsat_v2s64 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7 + + ; GFX6-LABEL: name: uaddsat_v2s64 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX6: [[UADDSAT:%[0-9]+]]:_(<2 x s64>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[UADDSAT]](<2 x s64>) + ; GFX8-LABEL: name: uaddsat_v2s64 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX8: [[UADDSAT:%[0-9]+]]:_(<2 x s64>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[UADDSAT]](<2 x s64>) + ; GFX9-LABEL: name: uaddsat_v2s64 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX9: [[UADDSAT:%[0-9]+]]:_(<2 x s64>) = G_UADDSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[UADDSAT]](<2 x s64>) + %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + %1:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + %2:_(<2 x s64>) = G_UADDSAT %0, %1 + $vgpr0_vgpr1_vgpr2_vgpr3 = COPY %2 +... diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir new file mode 100644 index 0000000000000..caf44cde8de06 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir @@ -0,0 +1,375 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=tahiti -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX6 %s +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=fiji -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX8 %s +# RUN: llc -global-isel-abort=0 -march=amdgcn -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s + +--- +name: usubsat_s7 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: usubsat_s7 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s7) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s7) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: usubsat_s7 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s7) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s7) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: usubsat_s7 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s7) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s7) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s7) = G_TRUNC %0 + %3:_(s7) = G_TRUNC %1 + %4:_(s7) = G_USUBSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: usubsat_s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: usubsat_s8 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s8) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: usubsat_s8 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s8) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: usubsat_s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s8) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s8) = G_TRUNC %0 + %3:_(s8) = G_TRUNC %1 + %4:_(s8) = G_USUBSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: usubsat_v2s8 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: usubsat_v2s8 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX6: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(<2 x s8>) = G_USUBSAT [[BITCAST]], [[BITCAST1]] + ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[USUBSAT]](<2 x s8>) + ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: usubsat_v2s8 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX8: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(<2 x s8>) = G_USUBSAT [[BITCAST]], [[BITCAST1]] + ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[USUBSAT]](<2 x s8>) + ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: usubsat_v2s8 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) + ; GFX9: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(<2 x s8>) = G_USUBSAT [[BITCAST]], [[BITCAST1]] + ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[USUBSAT]](<2 x s8>) + ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(<2 x s8>) = G_BITCAST %2 + %5:_(<2 x s8>) = G_BITCAST %3 + %6:_(<2 x s8>) = G_USUBSAT %4, %5 + %7:_(s16) = G_BITCAST %6 + %8:_(s32) = G_ANYEXT %7 + $vgpr0 = COPY %8 +... + +--- +name: usubsat_s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: usubsat_s16 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8-LABEL: name: usubsat_s16 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9-LABEL: name: usubsat_s16 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) + ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[TRUNC]], [[TRUNC1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s16) = G_TRUNC %0 + %3:_(s16) = G_TRUNC %1 + %4:_(s16) = G_USUBSAT %2, %3 + %5:_(s32) = G_ANYEXT %4 + $vgpr0 = COPY %5 +... + +--- +name: usubsat_v2s16 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: usubsat_v2s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX6: [[USUBSAT:%[0-9]+]]:_(<2 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0 = COPY [[USUBSAT]](<2 x s16>) + ; GFX8-LABEL: name: usubsat_v2s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX8: [[USUBSAT:%[0-9]+]]:_(<2 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0 = COPY [[USUBSAT]](<2 x s16>) + ; GFX9-LABEL: name: usubsat_v2s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 + ; GFX9: [[USUBSAT:%[0-9]+]]:_(<2 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[USUBSAT]](<2 x s16>) + %0:_(<2 x s16>) = COPY $vgpr0 + %1:_(<2 x s16>) = COPY $vgpr1 + %2:_(<2 x s16>) = G_USUBSAT %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: usubsat_v3s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2 + + ; GFX6-LABEL: name: usubsat_v3s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX6: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(<3 x s16>) = G_USUBSAT [[UV]], [[UV1]] + ; GFX6: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX6: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[USUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + ; GFX8-LABEL: name: usubsat_v3s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX8: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(<3 x s16>) = G_USUBSAT [[UV]], [[UV1]] + ; GFX8: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX8: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[USUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + ; GFX9-LABEL: name: usubsat_v3s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + ; GFX9: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(<3 x s16>) = G_USUBSAT [[UV]], [[UV1]] + ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF + ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[USUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) + %0:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 + %1:_(<3 x s16>), %2:_(<3 x s16>) = G_UNMERGE_VALUES %0 + %3:_(<3 x s16>) = G_USUBSAT %1, %2 + %4:_(<3 x s16>) = G_IMPLICIT_DEF + %5:_(<6 x s16>) = G_CONCAT_VECTORS %3, %4 + $vgpr0_vgpr1_vgpr2 = COPY %5 +... + +--- +name: usubsat_v4s16 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: usubsat_v4s16 + ; GFX6: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX6: [[USUBSAT:%[0-9]+]]:_(<4 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[USUBSAT]](<4 x s16>) + ; GFX8-LABEL: name: usubsat_v4s16 + ; GFX8: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX8: [[USUBSAT:%[0-9]+]]:_(<4 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[USUBSAT]](<4 x s16>) + ; GFX9-LABEL: name: usubsat_v4s16 + ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 + ; GFX9: [[USUBSAT:%[0-9]+]]:_(<4 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[USUBSAT]](<4 x s16>) + %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 + %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 + %2:_(<4 x s16>) = G_USUBSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: usubsat_s32 +body: | + bb.0: + liveins: $vgpr0, $vgpr1 + + ; GFX6-LABEL: name: usubsat_s32 + ; GFX6: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s32) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0 = COPY [[USUBSAT]](s32) + ; GFX8-LABEL: name: usubsat_s32 + ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s32) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0 = COPY [[USUBSAT]](s32) + ; GFX9-LABEL: name: usubsat_s32 + ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 + ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s32) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[USUBSAT]](s32) + %0:_(s32) = COPY $vgpr0 + %1:_(s32) = COPY $vgpr1 + %2:_(s32) = G_USUBSAT %0, %1 + $vgpr0 = COPY %2 +... + +--- +name: usubsat_v2s32 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: usubsat_v2s32 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX6: [[USUBSAT:%[0-9]+]]:_(<2 x s32>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[USUBSAT]](<2 x s32>) + ; GFX8-LABEL: name: usubsat_v2s32 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX8: [[USUBSAT:%[0-9]+]]:_(<2 x s32>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[USUBSAT]](<2 x s32>) + ; GFX9-LABEL: name: usubsat_v2s32 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 + ; GFX9: [[USUBSAT:%[0-9]+]]:_(<2 x s32>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[USUBSAT]](<2 x s32>) + %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 + %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 + %2:_(<2 x s32>) = G_USUBSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: usubsat_s64 +body: | + bb.0: + liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 + + ; GFX6-LABEL: name: usubsat_s64 + ; GFX6: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX6: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s64) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1 = COPY [[USUBSAT]](s64) + ; GFX8-LABEL: name: usubsat_s64 + ; GFX8: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX8: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s64) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1 = COPY [[USUBSAT]](s64) + ; GFX9-LABEL: name: usubsat_s64 + ; GFX9: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 + ; GFX9: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s64) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[USUBSAT]](s64) + %0:_(s64) = COPY $vgpr0_vgpr1 + %1:_(s64) = COPY $vgpr2_vgpr3 + %2:_(s64) = G_USUBSAT %0, %1 + $vgpr0_vgpr1 = COPY %2 +... + +--- +name: usubsat_v2s64 +body: | + bb.0: + liveins: $vgpr0_vgpr1_vgpr2_vgpr3, $vgpr4_vgpr5_vgpr6_vgpr7 + + ; GFX6-LABEL: name: usubsat_v2s64 + ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX6: [[USUBSAT:%[0-9]+]]:_(<2 x s64>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[USUBSAT]](<2 x s64>) + ; GFX8-LABEL: name: usubsat_v2s64 + ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX8: [[USUBSAT:%[0-9]+]]:_(<2 x s64>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[USUBSAT]](<2 x s64>) + ; GFX9-LABEL: name: usubsat_v2s64 + ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + ; GFX9: [[USUBSAT:%[0-9]+]]:_(<2 x s64>) = G_USUBSAT [[COPY]], [[COPY1]] + ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[USUBSAT]](<2 x s64>) + %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 + %1:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 + %2:_(<2 x s64>) = G_USUBSAT %0, %1 + $vgpr0_vgpr1_vgpr2_vgpr3 = COPY %2 +... From 6a8c11a11f6cf8d4ef1fa373c9546c33c69f8cb0 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 12 Jul 2020 13:58:53 -0400 Subject: [PATCH 135/771] GlobalISel: Implement widenScalar for saturating add/sub Add a placeholder legality rule for AMDGPU until the rest of the actions are handled. --- .../llvm/CodeGen/GlobalISel/LegalizerHelper.h | 2 + .../CodeGen/GlobalISel/LegalizerHelper.cpp | 43 ++++++++++ .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 6 ++ .../AMDGPU/GlobalISel/legalize-saddsat.mir | 84 +++++++++++++++---- .../AMDGPU/GlobalISel/legalize-ssubsat.mir | 84 +++++++++++++++---- .../AMDGPU/GlobalISel/legalize-uaddsat.mir | 84 +++++++++++++++---- .../AMDGPU/GlobalISel/legalize-usubsat.mir | 84 +++++++++++++++---- 7 files changed, 315 insertions(+), 72 deletions(-) diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index 0fe1d60b630db..058aacf38634d 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -163,6 +163,8 @@ class LegalizerHelper { widenScalarExtract(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); LegalizeResult widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, LLT WideTy); + LegalizeResult widenScalarAddSubSat(MachineInstr &MI, unsigned TypeIdx, + LLT WideTy); /// Helper function to split a wide generic register into bitwise blocks with /// the given Type (which implies the number of blocks needed). The generic diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 38590656d1f4b..7cd52df5b84d1 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1638,6 +1638,44 @@ LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx, return Legalized; } +LegalizerHelper::LegalizeResult +LegalizerHelper::widenScalarAddSubSat(MachineInstr &MI, unsigned TypeIdx, + LLT WideTy) { + bool IsSigned = MI.getOpcode() == TargetOpcode::G_SADDSAT || + MI.getOpcode() == TargetOpcode::G_SSUBSAT; + // We can convert this to: + // 1. Any extend iN to iM + // 2. SHL by M-N + // 3. [US][ADD|SUB]SAT + // 4. L/ASHR by M-N + // + // It may be more efficient to lower this to a min and a max operation in + // the higher precision arithmetic if the promoted operation isn't legal, + // but this decision is up to the target's lowering request. + Register DstReg = MI.getOperand(0).getReg(); + + unsigned NewBits = WideTy.getScalarSizeInBits(); + unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits(); + + auto LHS = MIRBuilder.buildAnyExt(WideTy, MI.getOperand(1)); + auto RHS = MIRBuilder.buildAnyExt(WideTy, MI.getOperand(2)); + auto ShiftK = MIRBuilder.buildConstant(WideTy, SHLAmount); + auto ShiftL = MIRBuilder.buildShl(WideTy, LHS, ShiftK); + auto ShiftR = MIRBuilder.buildShl(WideTy, RHS, ShiftK); + + auto WideInst = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy}, + {ShiftL, ShiftR}, MI.getFlags()); + + // Use a shift that will preserve the number of sign bits when the trunc is + // folded away. + auto Result = IsSigned ? MIRBuilder.buildAShr(WideTy, WideInst, ShiftK) + : MIRBuilder.buildLShr(WideTy, WideInst, ShiftK); + + MIRBuilder.buildTrunc(DstReg, Result); + MI.eraseFromParent(); + return Legalized; +} + LegalizerHelper::LegalizeResult LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { switch (MI.getOpcode()) { @@ -1674,6 +1712,11 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { MI.eraseFromParent(); return Legalized; } + case TargetOpcode::G_SADDSAT: + case TargetOpcode::G_SSUBSAT: + case TargetOpcode::G_UADDSAT: + case TargetOpcode::G_USUBSAT: + return widenScalarAddSubSat(MI, TypeIdx, WideTy); case TargetOpcode::G_CTTZ: case TargetOpcode::G_CTTZ_ZERO_UNDEF: case TargetOpcode::G_CTLZ: diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index 0802f2a2d08a7..2976794b49c3b 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -1427,6 +1427,12 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_, SextInReg.lowerFor({{S32}, {S64}}); } + // FIXME: Placeholder rule. Really depends on whether the clamp modifier is + // available, and is selectively legal for s16, s32, v2s16. + getActionDefinitionsBuilder({G_SADDSAT, G_SSUBSAT, G_UADDSAT, G_USUBSAT}) + .scalarize(0) + .clampScalar(0, S16, S32); + SextInReg .scalarize(0) .clampScalar(0, S32, S64) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir index 250645202af5a..50b639297b1db 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir @@ -14,25 +14,49 @@ body: | ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX6: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX6: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX6: [[SADDSAT:%[0-9]+]]:_(s7) = G_SADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s7) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[SADDSAT]](s16) + ; GFX6: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[ASHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s7) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC3]](s7) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: saddsat_s7 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX8: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX8: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX8: [[SADDSAT:%[0-9]+]]:_(s7) = G_SADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s7) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX8: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SADDSAT]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s7) = G_TRUNC [[ASHR]](s16) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s7) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: saddsat_s7 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX9: [[SADDSAT:%[0-9]+]]:_(s7) = G_SADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s7) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX9: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SADDSAT]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s7) = G_TRUNC [[ASHR]](s16) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s7) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s7) = G_TRUNC %0 @@ -53,25 +77,49 @@ body: | ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX6: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX6: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX6: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s8) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[SADDSAT]](s16) + ; GFX6: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[ASHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC3]](s8) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: saddsat_s8 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX8: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX8: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX8: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s8) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX8: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SADDSAT]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[ASHR]](s16) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s8) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: saddsat_s8 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX9: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SADDSAT]](s8) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX9: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SADDSAT]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[ASHR]](s16) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s8) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s8) = G_TRUNC %0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir index 53c9ba8410c72..3a4cbb1336f3a 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir @@ -14,25 +14,49 @@ body: | ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX6: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX6: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s7) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s7) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[SSUBSAT]](s16) + ; GFX6: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[ASHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s7) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC3]](s7) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: ssubsat_s7 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX8: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX8: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s7) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s7) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX8: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SSUBSAT]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s7) = G_TRUNC [[ASHR]](s16) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s7) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: ssubsat_s7 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s7) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s7) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX9: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SSUBSAT]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s7) = G_TRUNC [[ASHR]](s16) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s7) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s7) = G_TRUNC %0 @@ -53,25 +77,49 @@ body: | ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX6: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX6: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s8) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[SSUBSAT]](s16) + ; GFX6: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[ASHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC3]](s8) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: ssubsat_s8 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX8: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX8: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s8) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX8: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SSUBSAT]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[ASHR]](s16) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s8) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: ssubsat_s8 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[SSUBSAT]](s8) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX9: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SSUBSAT]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[ASHR]](s16) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s8) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s8) = G_TRUNC %0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir index 79d671214b549..ac229cd56dae6 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir @@ -14,25 +14,49 @@ body: | ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX6: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX6: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX6: [[UADDSAT:%[0-9]+]]:_(s7) = G_UADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s7) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UADDSAT]](s16) + ; GFX6: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ZEXT1]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s7) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC3]](s7) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: uaddsat_s7 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX8: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX8: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX8: [[UADDSAT:%[0-9]+]]:_(s7) = G_UADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s7) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX8: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[UADDSAT]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s7) = G_TRUNC [[LSHR]](s16) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s7) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: uaddsat_s7 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX9: [[UADDSAT:%[0-9]+]]:_(s7) = G_UADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s7) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX9: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[UADDSAT]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s7) = G_TRUNC [[LSHR]](s16) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s7) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s7) = G_TRUNC %0 @@ -53,25 +77,49 @@ body: | ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX6: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX6: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX6: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s8) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UADDSAT]](s16) + ; GFX6: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ZEXT1]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC3]](s8) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: uaddsat_s8 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX8: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX8: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX8: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s8) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX8: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[UADDSAT]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[LSHR]](s16) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s8) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: uaddsat_s8 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX9: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[TRUNC]], [[TRUNC1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[UADDSAT]](s8) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX9: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[UADDSAT]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[LSHR]](s16) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s8) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s8) = G_TRUNC %0 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir index caf44cde8de06..f0ea03d3d71f5 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir @@ -14,25 +14,49 @@ body: | ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX6: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX6: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX6: [[USUBSAT:%[0-9]+]]:_(s7) = G_USUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s7) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[USUBSAT]](s16) + ; GFX6: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ZEXT1]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s7) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC3]](s7) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: usubsat_s7 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX8: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX8: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX8: [[USUBSAT:%[0-9]+]]:_(s7) = G_USUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s7) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX8: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[USUBSAT]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s7) = G_TRUNC [[LSHR]](s16) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s7) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: usubsat_s7 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s7) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s7) = G_TRUNC [[COPY1]](s32) - ; GFX9: [[USUBSAT:%[0-9]+]]:_(s7) = G_USUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s7) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s7) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s7) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 9 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX9: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[USUBSAT]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s7) = G_TRUNC [[LSHR]](s16) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s7) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s7) = G_TRUNC %0 @@ -53,25 +77,49 @@ body: | ; GFX6: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX6: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX6: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX6: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s8) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[USUBSAT]](s16) + ; GFX6: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ZEXT1]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC3]](s8) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: usubsat_s8 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX8: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX8: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX8: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s8) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX8: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[USUBSAT]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[LSHR]](s16) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s8) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: usubsat_s8 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32) - ; GFX9: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[TRUNC]], [[TRUNC1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[USUBSAT]](s8) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC]](s8) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[TRUNC1]](s8) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX9: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[USUBSAT]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[LSHR]](s16) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[TRUNC2]](s8) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s8) = G_TRUNC %0 From 23ec773d197cc19c3f52e9d9dc7d3b57a59fb496 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 12 Jul 2020 16:11:53 -0400 Subject: [PATCH 136/771] GlobalISel: Implement fewerElementsVector for saturating add/sub --- .../CodeGen/GlobalISel/LegalizerHelper.cpp | 4 + .../AMDGPU/GlobalISel/legalize-saddsat.mir | 195 ++++++++++++++---- .../AMDGPU/GlobalISel/legalize-ssubsat.mir | 195 ++++++++++++++---- .../AMDGPU/GlobalISel/legalize-uaddsat.mir | 195 ++++++++++++++---- .../AMDGPU/GlobalISel/legalize-usubsat.mir | 195 ++++++++++++++---- 5 files changed, 604 insertions(+), 180 deletions(-) diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 7cd52df5b84d1..da519f99ad7e8 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -3457,6 +3457,10 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, case G_FSHL: case G_FSHR: case G_FREEZE: + case G_SADDSAT: + case G_SSUBSAT: + case G_UADDSAT: + case G_USUBSAT: return reduceOperationWidth(MI, TypeIdx, NarrowTy); case G_SHL: case G_LSHR: diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir index 50b639297b1db..8b3fbdaa73eba 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-saddsat.mir @@ -142,11 +142,25 @@ body: | ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX6: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX6: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX6: [[SADDSAT:%[0-9]+]]:_(<2 x s8>) = G_SADDSAT [[BITCAST]], [[BITCAST1]] - ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SADDSAT]](<2 x s8>) - ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX6: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[UV]], [[UV2]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[SADDSAT1]](s16) + ; GFX6: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[ASHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[SADDSAT]](s8), [[TRUNC3]](s8) + ; GFX6: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: saddsat_v2s8 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 @@ -154,11 +168,22 @@ body: | ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX8: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX8: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX8: [[SADDSAT:%[0-9]+]]:_(<2 x s8>) = G_SADDSAT [[BITCAST]], [[BITCAST1]] - ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SADDSAT]](<2 x s8>) - ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX8: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[UV]], [[UV2]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX8: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SADDSAT1]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[ASHR]](s16) + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[SADDSAT]](s8), [[TRUNC2]](s8) + ; GFX8: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: saddsat_v2s8 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 @@ -166,11 +191,22 @@ body: | ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX9: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX9: [[SADDSAT:%[0-9]+]]:_(<2 x s8>) = G_SADDSAT [[BITCAST]], [[BITCAST1]] - ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SADDSAT]](<2 x s8>) - ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX9: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s8) = G_SADDSAT [[UV]], [[UV2]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[SHL]], [[SHL1]] + ; GFX9: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SADDSAT1]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[ASHR]](s16) + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[SADDSAT]](s8), [[TRUNC2]](s8) + ; GFX9: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s16) = G_TRUNC %0 @@ -231,18 +267,30 @@ body: | ; GFX6-LABEL: name: saddsat_v2s16 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX6: [[SADDSAT:%[0-9]+]]:_(<2 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0 = COPY [[SADDSAT]](<2 x s16>) + ; GFX6: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX6: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV]], [[UV2]] + ; GFX6: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16) + ; GFX6: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) ; GFX8-LABEL: name: saddsat_v2s16 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX8: [[SADDSAT:%[0-9]+]]:_(<2 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0 = COPY [[SADDSAT]](<2 x s16>) + ; GFX8: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX8: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV]], [[UV2]] + ; GFX8: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16) + ; GFX8: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) ; GFX9-LABEL: name: saddsat_v2s16 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX9: [[SADDSAT:%[0-9]+]]:_(<2 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0 = COPY [[SADDSAT]](<2 x s16>) + ; GFX9: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV]], [[UV2]] + ; GFX9: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16) + ; GFX9: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) %0:_(<2 x s16>) = COPY $vgpr0 %1:_(<2 x s16>) = COPY $vgpr1 %2:_(<2 x s16>) = G_SADDSAT %0, %1 @@ -258,26 +306,41 @@ body: | ; GFX6-LABEL: name: saddsat_v3s16 ; GFX6: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX6: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX6: [[SADDSAT:%[0-9]+]]:_(<3 x s16>) = G_SADDSAT [[UV]], [[UV1]] + ; GFX6: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX6: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV2]], [[UV5]] + ; GFX6: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV3]], [[UV6]] + ; GFX6: [[SADDSAT2:%[0-9]+]]:_(s16) = G_SADDSAT [[UV4]], [[UV7]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16), [[SADDSAT2]](s16) ; GFX6: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX6: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) ; GFX8-LABEL: name: saddsat_v3s16 ; GFX8: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX8: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX8: [[SADDSAT:%[0-9]+]]:_(<3 x s16>) = G_SADDSAT [[UV]], [[UV1]] + ; GFX8: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX8: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV2]], [[UV5]] + ; GFX8: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV3]], [[UV6]] + ; GFX8: [[SADDSAT2:%[0-9]+]]:_(s16) = G_SADDSAT [[UV4]], [[UV7]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16), [[SADDSAT2]](s16) ; GFX8: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX8: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) ; GFX9-LABEL: name: saddsat_v3s16 ; GFX9: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX9: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX9: [[SADDSAT:%[0-9]+]]:_(<3 x s16>) = G_SADDSAT [[UV]], [[UV1]] + ; GFX9: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX9: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV2]], [[UV5]] + ; GFX9: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV3]], [[UV6]] + ; GFX9: [[SADDSAT2:%[0-9]+]]:_(s16) = G_SADDSAT [[UV4]], [[UV7]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16), [[SADDSAT2]](s16) ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) %0:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 %1:_(<3 x s16>), %2:_(<3 x s16>) = G_UNMERGE_VALUES %0 @@ -296,18 +359,36 @@ body: | ; GFX6-LABEL: name: saddsat_v4s16 ; GFX6: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX6: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX6: [[SADDSAT:%[0-9]+]]:_(<4 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1 = COPY [[SADDSAT]](<4 x s16>) + ; GFX6: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX6: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV]], [[UV4]] + ; GFX6: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV1]], [[UV5]] + ; GFX6: [[SADDSAT2:%[0-9]+]]:_(s16) = G_SADDSAT [[UV2]], [[UV6]] + ; GFX6: [[SADDSAT3:%[0-9]+]]:_(s16) = G_SADDSAT [[UV3]], [[UV7]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16), [[SADDSAT2]](s16), [[SADDSAT3]](s16) + ; GFX6: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) ; GFX8-LABEL: name: saddsat_v4s16 ; GFX8: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX8: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX8: [[SADDSAT:%[0-9]+]]:_(<4 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1 = COPY [[SADDSAT]](<4 x s16>) + ; GFX8: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX8: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV]], [[UV4]] + ; GFX8: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV1]], [[UV5]] + ; GFX8: [[SADDSAT2:%[0-9]+]]:_(s16) = G_SADDSAT [[UV2]], [[UV6]] + ; GFX8: [[SADDSAT3:%[0-9]+]]:_(s16) = G_SADDSAT [[UV3]], [[UV7]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16), [[SADDSAT2]](s16), [[SADDSAT3]](s16) + ; GFX8: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) ; GFX9-LABEL: name: saddsat_v4s16 ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX9: [[SADDSAT:%[0-9]+]]:_(<4 x s16>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[SADDSAT]](<4 x s16>) + ; GFX9: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX9: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s16) = G_SADDSAT [[UV]], [[UV4]] + ; GFX9: [[SADDSAT1:%[0-9]+]]:_(s16) = G_SADDSAT [[UV1]], [[UV5]] + ; GFX9: [[SADDSAT2:%[0-9]+]]:_(s16) = G_SADDSAT [[UV2]], [[UV6]] + ; GFX9: [[SADDSAT3:%[0-9]+]]:_(s16) = G_SADDSAT [[UV3]], [[UV7]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[SADDSAT]](s16), [[SADDSAT1]](s16), [[SADDSAT2]](s16), [[SADDSAT3]](s16) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 %2:_(<4 x s16>) = G_SADDSAT %0, %1 @@ -350,18 +431,30 @@ body: | ; GFX6-LABEL: name: saddsat_v2s32 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX6: [[SADDSAT:%[0-9]+]]:_(<2 x s32>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1 = COPY [[SADDSAT]](<2 x s32>) + ; GFX6: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX6: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s32) = G_SADDSAT [[UV]], [[UV2]] + ; GFX6: [[SADDSAT1:%[0-9]+]]:_(s32) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SADDSAT]](s32), [[SADDSAT1]](s32) + ; GFX6: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) ; GFX8-LABEL: name: saddsat_v2s32 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX8: [[SADDSAT:%[0-9]+]]:_(<2 x s32>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1 = COPY [[SADDSAT]](<2 x s32>) + ; GFX8: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX8: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s32) = G_SADDSAT [[UV]], [[UV2]] + ; GFX8: [[SADDSAT1:%[0-9]+]]:_(s32) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SADDSAT]](s32), [[SADDSAT1]](s32) + ; GFX8: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) ; GFX9-LABEL: name: saddsat_v2s32 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX9: [[SADDSAT:%[0-9]+]]:_(<2 x s32>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[SADDSAT]](<2 x s32>) + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s32) = G_SADDSAT [[UV]], [[UV2]] + ; GFX9: [[SADDSAT1:%[0-9]+]]:_(s32) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SADDSAT]](s32), [[SADDSAT1]](s32) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 %2:_(<2 x s32>) = G_SADDSAT %0, %1 @@ -404,18 +497,30 @@ body: | ; GFX6-LABEL: name: saddsat_v2s64 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX6: [[SADDSAT:%[0-9]+]]:_(<2 x s64>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SADDSAT]](<2 x s64>) + ; GFX6: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX6: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX6: [[SADDSAT:%[0-9]+]]:_(s64) = G_SADDSAT [[UV]], [[UV2]] + ; GFX6: [[SADDSAT1:%[0-9]+]]:_(s64) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SADDSAT]](s64), [[SADDSAT1]](s64) + ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; GFX8-LABEL: name: saddsat_v2s64 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX8: [[SADDSAT:%[0-9]+]]:_(<2 x s64>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SADDSAT]](<2 x s64>) + ; GFX8: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX8: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX8: [[SADDSAT:%[0-9]+]]:_(s64) = G_SADDSAT [[UV]], [[UV2]] + ; GFX8: [[SADDSAT1:%[0-9]+]]:_(s64) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SADDSAT]](s64), [[SADDSAT1]](s64) + ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; GFX9-LABEL: name: saddsat_v2s64 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX9: [[SADDSAT:%[0-9]+]]:_(<2 x s64>) = G_SADDSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SADDSAT]](<2 x s64>) + ; GFX9: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX9: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX9: [[SADDSAT:%[0-9]+]]:_(s64) = G_SADDSAT [[UV]], [[UV2]] + ; GFX9: [[SADDSAT1:%[0-9]+]]:_(s64) = G_SADDSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SADDSAT]](s64), [[SADDSAT1]](s64) + ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 %1:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 %2:_(<2 x s64>) = G_SADDSAT %0, %1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir index 3a4cbb1336f3a..31f119c13e5e1 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-ssubsat.mir @@ -142,11 +142,25 @@ body: | ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX6: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX6: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<2 x s8>) = G_SSUBSAT [[BITCAST]], [[BITCAST1]] - ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SSUBSAT]](<2 x s8>) - ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX6: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[SSUBSAT1]](s16) + ; GFX6: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[ASHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[SSUBSAT]](s8), [[TRUNC3]](s8) + ; GFX6: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: ssubsat_v2s8 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 @@ -154,11 +168,22 @@ body: | ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX8: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX8: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<2 x s8>) = G_SSUBSAT [[BITCAST]], [[BITCAST1]] - ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SSUBSAT]](<2 x s8>) - ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX8: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX8: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SSUBSAT1]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[ASHR]](s16) + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[SSUBSAT]](s8), [[TRUNC2]](s8) + ; GFX8: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: ssubsat_v2s8 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 @@ -166,11 +191,22 @@ body: | ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX9: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<2 x s8>) = G_SSUBSAT [[BITCAST]], [[BITCAST1]] - ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[SSUBSAT]](<2 x s8>) - ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX9: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s8) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[SHL]], [[SHL1]] + ; GFX9: [[ASHR:%[0-9]+]]:_(s16) = G_ASHR [[SSUBSAT1]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[ASHR]](s16) + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[SSUBSAT]](s8), [[TRUNC2]](s8) + ; GFX9: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s16) = G_TRUNC %0 @@ -231,18 +267,30 @@ body: | ; GFX6-LABEL: name: ssubsat_v2s16 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<2 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0 = COPY [[SSUBSAT]](<2 x s16>) + ; GFX6: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX6: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX6: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16) + ; GFX6: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) ; GFX8-LABEL: name: ssubsat_v2s16 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<2 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0 = COPY [[SSUBSAT]](<2 x s16>) + ; GFX8: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX8: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX8: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16) + ; GFX8: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) ; GFX9-LABEL: name: ssubsat_v2s16 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<2 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0 = COPY [[SSUBSAT]](<2 x s16>) + ; GFX9: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX9: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16) + ; GFX9: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) %0:_(<2 x s16>) = COPY $vgpr0 %1:_(<2 x s16>) = COPY $vgpr1 %2:_(<2 x s16>) = G_SSUBSAT %0, %1 @@ -258,26 +306,41 @@ body: | ; GFX6-LABEL: name: ssubsat_v3s16 ; GFX6: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX6: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<3 x s16>) = G_SSUBSAT [[UV]], [[UV1]] + ; GFX6: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX6: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV2]], [[UV5]] + ; GFX6: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV3]], [[UV6]] + ; GFX6: [[SSUBSAT2:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV4]], [[UV7]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16), [[SSUBSAT2]](s16) ; GFX6: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX6: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SSUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) ; GFX8-LABEL: name: ssubsat_v3s16 ; GFX8: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX8: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<3 x s16>) = G_SSUBSAT [[UV]], [[UV1]] + ; GFX8: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX8: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV2]], [[UV5]] + ; GFX8: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV3]], [[UV6]] + ; GFX8: [[SSUBSAT2:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV4]], [[UV7]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16), [[SSUBSAT2]](s16) ; GFX8: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX8: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SSUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) ; GFX9-LABEL: name: ssubsat_v3s16 ; GFX9: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX9: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<3 x s16>) = G_SSUBSAT [[UV]], [[UV1]] + ; GFX9: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX9: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV2]], [[UV5]] + ; GFX9: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV3]], [[UV6]] + ; GFX9: [[SSUBSAT2:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV4]], [[UV7]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16), [[SSUBSAT2]](s16) ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[SSUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) %0:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 %1:_(<3 x s16>), %2:_(<3 x s16>) = G_UNMERGE_VALUES %0 @@ -296,18 +359,36 @@ body: | ; GFX6-LABEL: name: ssubsat_v4s16 ; GFX6: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX6: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<4 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<4 x s16>) + ; GFX6: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX6: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV]], [[UV4]] + ; GFX6: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV1]], [[UV5]] + ; GFX6: [[SSUBSAT2:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV2]], [[UV6]] + ; GFX6: [[SSUBSAT3:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV3]], [[UV7]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16), [[SSUBSAT2]](s16), [[SSUBSAT3]](s16) + ; GFX6: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) ; GFX8-LABEL: name: ssubsat_v4s16 ; GFX8: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX8: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<4 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<4 x s16>) + ; GFX8: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX8: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV]], [[UV4]] + ; GFX8: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV1]], [[UV5]] + ; GFX8: [[SSUBSAT2:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV2]], [[UV6]] + ; GFX8: [[SSUBSAT3:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV3]], [[UV7]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16), [[SSUBSAT2]](s16), [[SSUBSAT3]](s16) + ; GFX8: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) ; GFX9-LABEL: name: ssubsat_v4s16 ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<4 x s16>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<4 x s16>) + ; GFX9: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX9: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV]], [[UV4]] + ; GFX9: [[SSUBSAT1:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV1]], [[UV5]] + ; GFX9: [[SSUBSAT2:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV2]], [[UV6]] + ; GFX9: [[SSUBSAT3:%[0-9]+]]:_(s16) = G_SSUBSAT [[UV3]], [[UV7]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[SSUBSAT]](s16), [[SSUBSAT1]](s16), [[SSUBSAT2]](s16), [[SSUBSAT3]](s16) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 %2:_(<4 x s16>) = G_SSUBSAT %0, %1 @@ -350,18 +431,30 @@ body: | ; GFX6-LABEL: name: ssubsat_v2s32 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<2 x s32>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<2 x s32>) + ; GFX6: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX6: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s32) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX6: [[SSUBSAT1:%[0-9]+]]:_(s32) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SSUBSAT]](s32), [[SSUBSAT1]](s32) + ; GFX6: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) ; GFX8-LABEL: name: ssubsat_v2s32 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<2 x s32>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<2 x s32>) + ; GFX8: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX8: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s32) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX8: [[SSUBSAT1:%[0-9]+]]:_(s32) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SSUBSAT]](s32), [[SSUBSAT1]](s32) + ; GFX8: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) ; GFX9-LABEL: name: ssubsat_v2s32 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<2 x s32>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[SSUBSAT]](<2 x s32>) + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s32) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX9: [[SSUBSAT1:%[0-9]+]]:_(s32) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[SSUBSAT]](s32), [[SSUBSAT1]](s32) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 %2:_(<2 x s32>) = G_SSUBSAT %0, %1 @@ -404,18 +497,30 @@ body: | ; GFX6-LABEL: name: ssubsat_v2s64 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX6: [[SSUBSAT:%[0-9]+]]:_(<2 x s64>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SSUBSAT]](<2 x s64>) + ; GFX6: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX6: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX6: [[SSUBSAT:%[0-9]+]]:_(s64) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX6: [[SSUBSAT1:%[0-9]+]]:_(s64) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SSUBSAT]](s64), [[SSUBSAT1]](s64) + ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; GFX8-LABEL: name: ssubsat_v2s64 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX8: [[SSUBSAT:%[0-9]+]]:_(<2 x s64>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SSUBSAT]](<2 x s64>) + ; GFX8: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX8: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX8: [[SSUBSAT:%[0-9]+]]:_(s64) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX8: [[SSUBSAT1:%[0-9]+]]:_(s64) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SSUBSAT]](s64), [[SSUBSAT1]](s64) + ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; GFX9-LABEL: name: ssubsat_v2s64 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX9: [[SSUBSAT:%[0-9]+]]:_(<2 x s64>) = G_SSUBSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[SSUBSAT]](<2 x s64>) + ; GFX9: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX9: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX9: [[SSUBSAT:%[0-9]+]]:_(s64) = G_SSUBSAT [[UV]], [[UV2]] + ; GFX9: [[SSUBSAT1:%[0-9]+]]:_(s64) = G_SSUBSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[SSUBSAT]](s64), [[SSUBSAT1]](s64) + ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 %1:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 %2:_(<2 x s64>) = G_SSUBSAT %0, %1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir index ac229cd56dae6..e080bde81b3a5 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-uaddsat.mir @@ -142,11 +142,25 @@ body: | ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX6: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX6: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX6: [[UADDSAT:%[0-9]+]]:_(<2 x s8>) = G_UADDSAT [[BITCAST]], [[BITCAST1]] - ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[UADDSAT]](<2 x s8>) - ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX6: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[UV]], [[UV2]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[UADDSAT1]](s16) + ; GFX6: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ZEXT1]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[UADDSAT]](s8), [[TRUNC3]](s8) + ; GFX6: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: uaddsat_v2s8 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 @@ -154,11 +168,22 @@ body: | ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX8: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX8: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX8: [[UADDSAT:%[0-9]+]]:_(<2 x s8>) = G_UADDSAT [[BITCAST]], [[BITCAST1]] - ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[UADDSAT]](<2 x s8>) - ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX8: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[UV]], [[UV2]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX8: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[UADDSAT1]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[LSHR]](s16) + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[UADDSAT]](s8), [[TRUNC2]](s8) + ; GFX8: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: uaddsat_v2s8 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 @@ -166,11 +191,22 @@ body: | ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX9: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX9: [[UADDSAT:%[0-9]+]]:_(<2 x s8>) = G_UADDSAT [[BITCAST]], [[BITCAST1]] - ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[UADDSAT]](<2 x s8>) - ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX9: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s8) = G_UADDSAT [[UV]], [[UV2]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[SHL]], [[SHL1]] + ; GFX9: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[UADDSAT1]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[LSHR]](s16) + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[UADDSAT]](s8), [[TRUNC2]](s8) + ; GFX9: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s16) = G_TRUNC %0 @@ -231,18 +267,30 @@ body: | ; GFX6-LABEL: name: uaddsat_v2s16 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX6: [[UADDSAT:%[0-9]+]]:_(<2 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0 = COPY [[UADDSAT]](<2 x s16>) + ; GFX6: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX6: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV]], [[UV2]] + ; GFX6: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16) + ; GFX6: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) ; GFX8-LABEL: name: uaddsat_v2s16 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX8: [[UADDSAT:%[0-9]+]]:_(<2 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0 = COPY [[UADDSAT]](<2 x s16>) + ; GFX8: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX8: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV]], [[UV2]] + ; GFX8: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16) + ; GFX8: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) ; GFX9-LABEL: name: uaddsat_v2s16 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX9: [[UADDSAT:%[0-9]+]]:_(<2 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0 = COPY [[UADDSAT]](<2 x s16>) + ; GFX9: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV]], [[UV2]] + ; GFX9: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16) + ; GFX9: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) %0:_(<2 x s16>) = COPY $vgpr0 %1:_(<2 x s16>) = COPY $vgpr1 %2:_(<2 x s16>) = G_UADDSAT %0, %1 @@ -258,26 +306,41 @@ body: | ; GFX6-LABEL: name: uaddsat_v3s16 ; GFX6: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX6: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX6: [[UADDSAT:%[0-9]+]]:_(<3 x s16>) = G_UADDSAT [[UV]], [[UV1]] + ; GFX6: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX6: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV2]], [[UV5]] + ; GFX6: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV3]], [[UV6]] + ; GFX6: [[UADDSAT2:%[0-9]+]]:_(s16) = G_UADDSAT [[UV4]], [[UV7]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16), [[UADDSAT2]](s16) ; GFX6: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX6: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[UADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) ; GFX8-LABEL: name: uaddsat_v3s16 ; GFX8: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX8: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX8: [[UADDSAT:%[0-9]+]]:_(<3 x s16>) = G_UADDSAT [[UV]], [[UV1]] + ; GFX8: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX8: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV2]], [[UV5]] + ; GFX8: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV3]], [[UV6]] + ; GFX8: [[UADDSAT2:%[0-9]+]]:_(s16) = G_UADDSAT [[UV4]], [[UV7]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16), [[UADDSAT2]](s16) ; GFX8: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX8: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[UADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) ; GFX9-LABEL: name: uaddsat_v3s16 ; GFX9: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX9: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX9: [[UADDSAT:%[0-9]+]]:_(<3 x s16>) = G_UADDSAT [[UV]], [[UV1]] + ; GFX9: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX9: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV2]], [[UV5]] + ; GFX9: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV3]], [[UV6]] + ; GFX9: [[UADDSAT2:%[0-9]+]]:_(s16) = G_UADDSAT [[UV4]], [[UV7]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16), [[UADDSAT2]](s16) ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[UADDSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) %0:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 %1:_(<3 x s16>), %2:_(<3 x s16>) = G_UNMERGE_VALUES %0 @@ -296,18 +359,36 @@ body: | ; GFX6-LABEL: name: uaddsat_v4s16 ; GFX6: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX6: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX6: [[UADDSAT:%[0-9]+]]:_(<4 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1 = COPY [[UADDSAT]](<4 x s16>) + ; GFX6: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX6: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV]], [[UV4]] + ; GFX6: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV1]], [[UV5]] + ; GFX6: [[UADDSAT2:%[0-9]+]]:_(s16) = G_UADDSAT [[UV2]], [[UV6]] + ; GFX6: [[UADDSAT3:%[0-9]+]]:_(s16) = G_UADDSAT [[UV3]], [[UV7]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16), [[UADDSAT2]](s16), [[UADDSAT3]](s16) + ; GFX6: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) ; GFX8-LABEL: name: uaddsat_v4s16 ; GFX8: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX8: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX8: [[UADDSAT:%[0-9]+]]:_(<4 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1 = COPY [[UADDSAT]](<4 x s16>) + ; GFX8: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX8: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV]], [[UV4]] + ; GFX8: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV1]], [[UV5]] + ; GFX8: [[UADDSAT2:%[0-9]+]]:_(s16) = G_UADDSAT [[UV2]], [[UV6]] + ; GFX8: [[UADDSAT3:%[0-9]+]]:_(s16) = G_UADDSAT [[UV3]], [[UV7]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16), [[UADDSAT2]](s16), [[UADDSAT3]](s16) + ; GFX8: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) ; GFX9-LABEL: name: uaddsat_v4s16 ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX9: [[UADDSAT:%[0-9]+]]:_(<4 x s16>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[UADDSAT]](<4 x s16>) + ; GFX9: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX9: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s16) = G_UADDSAT [[UV]], [[UV4]] + ; GFX9: [[UADDSAT1:%[0-9]+]]:_(s16) = G_UADDSAT [[UV1]], [[UV5]] + ; GFX9: [[UADDSAT2:%[0-9]+]]:_(s16) = G_UADDSAT [[UV2]], [[UV6]] + ; GFX9: [[UADDSAT3:%[0-9]+]]:_(s16) = G_UADDSAT [[UV3]], [[UV7]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[UADDSAT]](s16), [[UADDSAT1]](s16), [[UADDSAT2]](s16), [[UADDSAT3]](s16) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 %2:_(<4 x s16>) = G_UADDSAT %0, %1 @@ -350,18 +431,30 @@ body: | ; GFX6-LABEL: name: uaddsat_v2s32 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX6: [[UADDSAT:%[0-9]+]]:_(<2 x s32>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1 = COPY [[UADDSAT]](<2 x s32>) + ; GFX6: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX6: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s32) = G_UADDSAT [[UV]], [[UV2]] + ; GFX6: [[UADDSAT1:%[0-9]+]]:_(s32) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UADDSAT]](s32), [[UADDSAT1]](s32) + ; GFX6: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) ; GFX8-LABEL: name: uaddsat_v2s32 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX8: [[UADDSAT:%[0-9]+]]:_(<2 x s32>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1 = COPY [[UADDSAT]](<2 x s32>) + ; GFX8: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX8: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s32) = G_UADDSAT [[UV]], [[UV2]] + ; GFX8: [[UADDSAT1:%[0-9]+]]:_(s32) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UADDSAT]](s32), [[UADDSAT1]](s32) + ; GFX8: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) ; GFX9-LABEL: name: uaddsat_v2s32 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX9: [[UADDSAT:%[0-9]+]]:_(<2 x s32>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[UADDSAT]](<2 x s32>) + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s32) = G_UADDSAT [[UV]], [[UV2]] + ; GFX9: [[UADDSAT1:%[0-9]+]]:_(s32) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[UADDSAT]](s32), [[UADDSAT1]](s32) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 %2:_(<2 x s32>) = G_UADDSAT %0, %1 @@ -404,18 +497,30 @@ body: | ; GFX6-LABEL: name: uaddsat_v2s64 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX6: [[UADDSAT:%[0-9]+]]:_(<2 x s64>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[UADDSAT]](<2 x s64>) + ; GFX6: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX6: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX6: [[UADDSAT:%[0-9]+]]:_(s64) = G_UADDSAT [[UV]], [[UV2]] + ; GFX6: [[UADDSAT1:%[0-9]+]]:_(s64) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[UADDSAT]](s64), [[UADDSAT1]](s64) + ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; GFX8-LABEL: name: uaddsat_v2s64 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX8: [[UADDSAT:%[0-9]+]]:_(<2 x s64>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[UADDSAT]](<2 x s64>) + ; GFX8: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX8: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX8: [[UADDSAT:%[0-9]+]]:_(s64) = G_UADDSAT [[UV]], [[UV2]] + ; GFX8: [[UADDSAT1:%[0-9]+]]:_(s64) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[UADDSAT]](s64), [[UADDSAT1]](s64) + ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; GFX9-LABEL: name: uaddsat_v2s64 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX9: [[UADDSAT:%[0-9]+]]:_(<2 x s64>) = G_UADDSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[UADDSAT]](<2 x s64>) + ; GFX9: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX9: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX9: [[UADDSAT:%[0-9]+]]:_(s64) = G_UADDSAT [[UV]], [[UV2]] + ; GFX9: [[UADDSAT1:%[0-9]+]]:_(s64) = G_UADDSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[UADDSAT]](s64), [[UADDSAT1]](s64) + ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 %1:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 %2:_(<2 x s64>) = G_UADDSAT %0, %1 diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir index f0ea03d3d71f5..56a1f1baded55 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-usubsat.mir @@ -142,11 +142,25 @@ body: | ; GFX6: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX6: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX6: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX6: [[USUBSAT:%[0-9]+]]:_(<2 x s8>) = G_USUBSAT [[BITCAST]], [[BITCAST1]] - ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[USUBSAT]](<2 x s8>) - ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX6: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX6: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX6: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX6: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[UV]], [[UV2]] + ; GFX6: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX6: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX6: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX6: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX6: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX6: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX6: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[C]](s16) + ; GFX6: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[USUBSAT1]](s16) + ; GFX6: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ZEXT1]], [[ZEXT]](s32) + ; GFX6: [[TRUNC2:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR]](s32) + ; GFX6: [[TRUNC3:%[0-9]+]]:_(s8) = G_TRUNC [[TRUNC2]](s16) + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[USUBSAT]](s8), [[TRUNC3]](s8) + ; GFX6: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX6: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX6: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX6: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX8-LABEL: name: usubsat_v2s8 ; GFX8: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 @@ -154,11 +168,22 @@ body: | ; GFX8: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX8: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX8: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX8: [[USUBSAT:%[0-9]+]]:_(<2 x s8>) = G_USUBSAT [[BITCAST]], [[BITCAST1]] - ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[USUBSAT]](<2 x s8>) - ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX8: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX8: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX8: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX8: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[UV]], [[UV2]] + ; GFX8: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX8: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX8: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX8: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX8: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX8: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX8: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[USUBSAT1]], [[C]](s16) + ; GFX8: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[LSHR]](s16) + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[USUBSAT]](s8), [[TRUNC2]](s8) + ; GFX8: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX8: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX8: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX8: $vgpr0 = COPY [[ANYEXT2]](s32) ; GFX9-LABEL: name: usubsat_v2s8 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 @@ -166,11 +191,22 @@ body: | ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9: [[BITCAST:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC]](s16) ; GFX9: [[BITCAST1:%[0-9]+]]:_(<2 x s8>) = G_BITCAST [[TRUNC1]](s16) - ; GFX9: [[USUBSAT:%[0-9]+]]:_(<2 x s8>) = G_USUBSAT [[BITCAST]], [[BITCAST1]] - ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[USUBSAT]](<2 x s8>) - ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV]](s8), [[UV1]](s8) - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) - ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) + ; GFX9: [[UV:%[0-9]+]]:_(s8), [[UV1:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST]](<2 x s8>) + ; GFX9: [[UV2:%[0-9]+]]:_(s8), [[UV3:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BITCAST1]](<2 x s8>) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s8) = G_USUBSAT [[UV]], [[UV2]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s16) = G_ANYEXT [[UV1]](s8) + ; GFX9: [[ANYEXT1:%[0-9]+]]:_(s16) = G_ANYEXT [[UV3]](s8) + ; GFX9: [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 8 + ; GFX9: [[SHL:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT]], [[C]](s16) + ; GFX9: [[SHL1:%[0-9]+]]:_(s16) = G_SHL [[ANYEXT1]], [[C]](s16) + ; GFX9: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[SHL]], [[SHL1]] + ; GFX9: [[LSHR:%[0-9]+]]:_(s16) = G_LSHR [[USUBSAT1]], [[C]](s16) + ; GFX9: [[TRUNC2:%[0-9]+]]:_(s8) = G_TRUNC [[LSHR]](s16) + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s8>) = G_BUILD_VECTOR [[USUBSAT]](s8), [[TRUNC2]](s8) + ; GFX9: [[UV4:%[0-9]+]]:_(s8), [[UV5:%[0-9]+]]:_(s8) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<2 x s8>) + ; GFX9: [[MV:%[0-9]+]]:_(s16) = G_MERGE_VALUES [[UV4]](s8), [[UV5]](s8) + ; GFX9: [[ANYEXT2:%[0-9]+]]:_(s32) = G_ANYEXT [[MV]](s16) + ; GFX9: $vgpr0 = COPY [[ANYEXT2]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s16) = G_TRUNC %0 @@ -231,18 +267,30 @@ body: | ; GFX6-LABEL: name: usubsat_v2s16 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX6: [[USUBSAT:%[0-9]+]]:_(<2 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0 = COPY [[USUBSAT]](<2 x s16>) + ; GFX6: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX6: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV]], [[UV2]] + ; GFX6: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16) + ; GFX6: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) ; GFX8-LABEL: name: usubsat_v2s16 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX8: [[USUBSAT:%[0-9]+]]:_(<2 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0 = COPY [[USUBSAT]](<2 x s16>) + ; GFX8: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX8: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV]], [[UV2]] + ; GFX8: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16) + ; GFX8: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) ; GFX9-LABEL: name: usubsat_v2s16 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 - ; GFX9: [[USUBSAT:%[0-9]+]]:_(<2 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0 = COPY [[USUBSAT]](<2 x s16>) + ; GFX9: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<2 x s16>) + ; GFX9: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<2 x s16>) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV]], [[UV2]] + ; GFX9: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16) + ; GFX9: $vgpr0 = COPY [[BUILD_VECTOR]](<2 x s16>) %0:_(<2 x s16>) = COPY $vgpr0 %1:_(<2 x s16>) = COPY $vgpr1 %2:_(<2 x s16>) = G_USUBSAT %0, %1 @@ -258,26 +306,41 @@ body: | ; GFX6-LABEL: name: usubsat_v3s16 ; GFX6: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX6: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX6: [[USUBSAT:%[0-9]+]]:_(<3 x s16>) = G_USUBSAT [[UV]], [[UV1]] + ; GFX6: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX6: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV2]], [[UV5]] + ; GFX6: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV3]], [[UV6]] + ; GFX6: [[USUBSAT2:%[0-9]+]]:_(s16) = G_USUBSAT [[UV4]], [[UV7]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16), [[USUBSAT2]](s16) ; GFX6: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX6: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[USUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX6: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX6: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) ; GFX8-LABEL: name: usubsat_v3s16 ; GFX8: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX8: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX8: [[USUBSAT:%[0-9]+]]:_(<3 x s16>) = G_USUBSAT [[UV]], [[UV1]] + ; GFX8: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX8: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV2]], [[UV5]] + ; GFX8: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV3]], [[UV6]] + ; GFX8: [[USUBSAT2:%[0-9]+]]:_(s16) = G_USUBSAT [[UV4]], [[UV7]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16), [[USUBSAT2]](s16) ; GFX8: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX8: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[USUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX8: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX8: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) ; GFX9-LABEL: name: usubsat_v3s16 ; GFX9: [[COPY:%[0-9]+]]:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 ; GFX9: [[UV:%[0-9]+]]:_(<3 x s16>), [[UV1:%[0-9]+]]:_(<3 x s16>) = G_UNMERGE_VALUES [[COPY]](<6 x s16>) - ; GFX9: [[USUBSAT:%[0-9]+]]:_(<3 x s16>) = G_USUBSAT [[UV]], [[UV1]] + ; GFX9: [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16), [[UV4:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV]](<3 x s16>) + ; GFX9: [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[UV1]](<3 x s16>) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV2]], [[UV5]] + ; GFX9: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV3]], [[UV6]] + ; GFX9: [[USUBSAT2:%[0-9]+]]:_(s16) = G_USUBSAT [[UV4]], [[UV7]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<3 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16), [[USUBSAT2]](s16) ; GFX9: [[DEF:%[0-9]+]]:_(<4 x s16>) = G_IMPLICIT_DEF ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[DEF]](<4 x s16>), 0 - ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[USUBSAT]](<3 x s16>), [[EXTRACT]](<3 x s16>) + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<6 x s16>) = G_CONCAT_VECTORS [[BUILD_VECTOR]](<3 x s16>), [[EXTRACT]](<3 x s16>) ; GFX9: $vgpr0_vgpr1_vgpr2 = COPY [[CONCAT_VECTORS]](<6 x s16>) %0:_(<6 x s16>) = COPY $vgpr0_vgpr1_vgpr2 %1:_(<3 x s16>), %2:_(<3 x s16>) = G_UNMERGE_VALUES %0 @@ -296,18 +359,36 @@ body: | ; GFX6-LABEL: name: usubsat_v4s16 ; GFX6: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX6: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX6: [[USUBSAT:%[0-9]+]]:_(<4 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1 = COPY [[USUBSAT]](<4 x s16>) + ; GFX6: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX6: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV]], [[UV4]] + ; GFX6: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV1]], [[UV5]] + ; GFX6: [[USUBSAT2:%[0-9]+]]:_(s16) = G_USUBSAT [[UV2]], [[UV6]] + ; GFX6: [[USUBSAT3:%[0-9]+]]:_(s16) = G_USUBSAT [[UV3]], [[UV7]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16), [[USUBSAT2]](s16), [[USUBSAT3]](s16) + ; GFX6: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) ; GFX8-LABEL: name: usubsat_v4s16 ; GFX8: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX8: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX8: [[USUBSAT:%[0-9]+]]:_(<4 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1 = COPY [[USUBSAT]](<4 x s16>) + ; GFX8: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX8: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV]], [[UV4]] + ; GFX8: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV1]], [[UV5]] + ; GFX8: [[USUBSAT2:%[0-9]+]]:_(s16) = G_USUBSAT [[UV2]], [[UV6]] + ; GFX8: [[USUBSAT3:%[0-9]+]]:_(s16) = G_USUBSAT [[UV3]], [[UV7]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16), [[USUBSAT2]](s16), [[USUBSAT3]](s16) + ; GFX8: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) ; GFX9-LABEL: name: usubsat_v4s16 ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 - ; GFX9: [[USUBSAT:%[0-9]+]]:_(<4 x s16>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[USUBSAT]](<4 x s16>) + ; GFX9: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) + ; GFX9: [[UV4:%[0-9]+]]:_(s16), [[UV5:%[0-9]+]]:_(s16), [[UV6:%[0-9]+]]:_(s16), [[UV7:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s16) = G_USUBSAT [[UV]], [[UV4]] + ; GFX9: [[USUBSAT1:%[0-9]+]]:_(s16) = G_USUBSAT [[UV1]], [[UV5]] + ; GFX9: [[USUBSAT2:%[0-9]+]]:_(s16) = G_USUBSAT [[UV2]], [[UV6]] + ; GFX9: [[USUBSAT3:%[0-9]+]]:_(s16) = G_USUBSAT [[UV3]], [[UV7]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s16>) = G_BUILD_VECTOR [[USUBSAT]](s16), [[USUBSAT1]](s16), [[USUBSAT2]](s16), [[USUBSAT3]](s16) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<4 x s16>) %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 %2:_(<4 x s16>) = G_USUBSAT %0, %1 @@ -350,18 +431,30 @@ body: | ; GFX6-LABEL: name: usubsat_v2s32 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX6: [[USUBSAT:%[0-9]+]]:_(<2 x s32>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1 = COPY [[USUBSAT]](<2 x s32>) + ; GFX6: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX6: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s32) = G_USUBSAT [[UV]], [[UV2]] + ; GFX6: [[USUBSAT1:%[0-9]+]]:_(s32) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[USUBSAT]](s32), [[USUBSAT1]](s32) + ; GFX6: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) ; GFX8-LABEL: name: usubsat_v2s32 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX8: [[USUBSAT:%[0-9]+]]:_(<2 x s32>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1 = COPY [[USUBSAT]](<2 x s32>) + ; GFX8: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX8: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s32) = G_USUBSAT [[UV]], [[UV2]] + ; GFX8: [[USUBSAT1:%[0-9]+]]:_(s32) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[USUBSAT]](s32), [[USUBSAT1]](s32) + ; GFX8: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) ; GFX9-LABEL: name: usubsat_v2s32 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 - ; GFX9: [[USUBSAT:%[0-9]+]]:_(<2 x s32>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[USUBSAT]](<2 x s32>) + ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) + ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s32) = G_USUBSAT [[UV]], [[UV2]] + ; GFX9: [[USUBSAT1:%[0-9]+]]:_(s32) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[USUBSAT]](s32), [[USUBSAT1]](s32) + ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 %2:_(<2 x s32>) = G_USUBSAT %0, %1 @@ -404,18 +497,30 @@ body: | ; GFX6-LABEL: name: usubsat_v2s64 ; GFX6: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX6: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX6: [[USUBSAT:%[0-9]+]]:_(<2 x s64>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[USUBSAT]](<2 x s64>) + ; GFX6: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX6: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX6: [[USUBSAT:%[0-9]+]]:_(s64) = G_USUBSAT [[UV]], [[UV2]] + ; GFX6: [[USUBSAT1:%[0-9]+]]:_(s64) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX6: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[USUBSAT]](s64), [[USUBSAT1]](s64) + ; GFX6: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; GFX8-LABEL: name: usubsat_v2s64 ; GFX8: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX8: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX8: [[USUBSAT:%[0-9]+]]:_(<2 x s64>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[USUBSAT]](<2 x s64>) + ; GFX8: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX8: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX8: [[USUBSAT:%[0-9]+]]:_(s64) = G_USUBSAT [[UV]], [[UV2]] + ; GFX8: [[USUBSAT1:%[0-9]+]]:_(s64) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX8: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[USUBSAT]](s64), [[USUBSAT1]](s64) + ; GFX8: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) ; GFX9-LABEL: name: usubsat_v2s64 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 - ; GFX9: [[USUBSAT:%[0-9]+]]:_(<2 x s64>) = G_USUBSAT [[COPY]], [[COPY1]] - ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[USUBSAT]](<2 x s64>) + ; GFX9: [[UV:%[0-9]+]]:_(s64), [[UV1:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY]](<2 x s64>) + ; GFX9: [[UV2:%[0-9]+]]:_(s64), [[UV3:%[0-9]+]]:_(s64) = G_UNMERGE_VALUES [[COPY1]](<2 x s64>) + ; GFX9: [[USUBSAT:%[0-9]+]]:_(s64) = G_USUBSAT [[UV]], [[UV2]] + ; GFX9: [[USUBSAT1:%[0-9]+]]:_(s64) = G_USUBSAT [[UV1]], [[UV3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s64>) = G_BUILD_VECTOR [[USUBSAT]](s64), [[USUBSAT1]](s64) + ; GFX9: $vgpr0_vgpr1_vgpr2_vgpr3 = COPY [[BUILD_VECTOR]](<2 x s64>) %0:_(<2 x s64>) = COPY $vgpr0_vgpr1_vgpr2_vgpr3 %1:_(<2 x s64>) = COPY $vgpr4_vgpr5_vgpr6_vgpr7 %2:_(<2 x s64>) = G_USUBSAT %0, %1 From 83aaa2085e5f44a287a3ac90532197a077c0160e Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sun, 12 Jul 2020 14:03:23 -0400 Subject: [PATCH 137/771] GlobalISel: Define equivalent nodes for saturating add/sub --- llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index b8f03bcec16b8..150834e65b2dc 100644 --- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -67,6 +67,10 @@ def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; +def : GINodeEquiv; +def : GINodeEquiv; +def : GINodeEquiv; +def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; From 51b20152e66cc6f092675d36b8367320bda31955 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 13 Jul 2020 11:21:40 -0700 Subject: [PATCH 138/771] [JITLink] Apply MSVCPError workaround to a1fc26030a42. Hopefully this will get the Windows bots building again. --- .../llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h b/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h index 3bb56f4d96158..0c8514a60a507 100644 --- a/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h +++ b/llvm/include/llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h @@ -17,6 +17,7 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/Support/Error.h" #include "llvm/Support/Memory.h" +#include "llvm/Support/MSVCErrorWorkarounds.h" #include #include @@ -78,7 +79,7 @@ class JITLinkMemoryManager { /// Calls finalizeAsync and waits for completion. Error finalize() { - std::promise FinalizeResultP; + std::promise FinalizeResultP; auto FinalizeResultF = FinalizeResultP.get_future(); finalizeAsync( [&](Error Err) { FinalizeResultP.set_value(std::move(Err)); }); From 14f738b350147c18241ead3d62f4367d65ff38ad Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 13 Jul 2020 20:48:12 +0200 Subject: [PATCH 139/771] [NewGVN] Rename xfail tests (NFC) Add an -xfail.ll suffix to tests marked XFAIL, so these files can be split into passing and failing parts. --- ...007-07-31-NoDomInherit.ll => 2007-07-31-NoDomInherit-xfail.ll} | 0 .../{2008-02-12-UndefLoad.ll => 2008-02-12-UndefLoad-xfail.ll} | 0 ...edScatterGather.ll => 2016-08-30-MaskedScatterGather-xfail.ll} | 0 .../Transforms/NewGVN/{assume-equal.ll => assume-equal-xfail.ll} | 0 .../NewGVN/{calls-nonlocal.ll => calls-nonlocal-xfail.ll} | 0 llvm/test/Transforms/NewGVN/{cond_br2.ll => cond_br2-xfail.ll} | 0 llvm/test/Transforms/NewGVN/{debugloc.ll => debugloc-xfail.ll} | 0 llvm/test/Transforms/NewGVN/{fence.ll => fence-xfail.ll} | 0 .../NewGVN/{invariant.group.ll => invariant.group-xfail.ll} | 0 .../NewGVN/{nonescaping-malloc.ll => nonescaping-malloc-xfail.ll} | 0 .../Transforms/NewGVN/{opt-remarks.ll => opt-remarks-xfail.ll} | 0 llvm/test/Transforms/NewGVN/{pr10820.ll => pr10820-xfail.ll} | 0 llvm/test/Transforms/NewGVN/{pr14166.ll => pr14166-xfail.ll} | 0 .../Transforms/NewGVN/{pre-new-inst.ll => pre-new-inst-xfail.ll} | 0 .../NewGVN/{rle-must-alias.ll => rle-must-alias-xfail.ll} | 0 .../{rle-no-phi-translate.ll => rle-no-phi-translate-xfail.ll} | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename llvm/test/Transforms/NewGVN/{2007-07-31-NoDomInherit.ll => 2007-07-31-NoDomInherit-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{2008-02-12-UndefLoad.ll => 2008-02-12-UndefLoad-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{2016-08-30-MaskedScatterGather.ll => 2016-08-30-MaskedScatterGather-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{assume-equal.ll => assume-equal-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{calls-nonlocal.ll => calls-nonlocal-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{cond_br2.ll => cond_br2-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{debugloc.ll => debugloc-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{fence.ll => fence-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{invariant.group.ll => invariant.group-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{nonescaping-malloc.ll => nonescaping-malloc-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{opt-remarks.ll => opt-remarks-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{pr10820.ll => pr10820-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{pr14166.ll => pr14166-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{pre-new-inst.ll => pre-new-inst-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{rle-must-alias.ll => rle-must-alias-xfail.ll} (100%) rename llvm/test/Transforms/NewGVN/{rle-no-phi-translate.ll => rle-no-phi-translate-xfail.ll} (100%) diff --git a/llvm/test/Transforms/NewGVN/2007-07-31-NoDomInherit.ll b/llvm/test/Transforms/NewGVN/2007-07-31-NoDomInherit-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/2007-07-31-NoDomInherit.ll rename to llvm/test/Transforms/NewGVN/2007-07-31-NoDomInherit-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/2008-02-12-UndefLoad.ll b/llvm/test/Transforms/NewGVN/2008-02-12-UndefLoad-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/2008-02-12-UndefLoad.ll rename to llvm/test/Transforms/NewGVN/2008-02-12-UndefLoad-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll b/llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather.ll rename to llvm/test/Transforms/NewGVN/2016-08-30-MaskedScatterGather-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/assume-equal.ll b/llvm/test/Transforms/NewGVN/assume-equal-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/assume-equal.ll rename to llvm/test/Transforms/NewGVN/assume-equal-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/calls-nonlocal.ll b/llvm/test/Transforms/NewGVN/calls-nonlocal-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/calls-nonlocal.ll rename to llvm/test/Transforms/NewGVN/calls-nonlocal-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/cond_br2.ll b/llvm/test/Transforms/NewGVN/cond_br2-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/cond_br2.ll rename to llvm/test/Transforms/NewGVN/cond_br2-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/debugloc.ll b/llvm/test/Transforms/NewGVN/debugloc-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/debugloc.ll rename to llvm/test/Transforms/NewGVN/debugloc-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/fence.ll b/llvm/test/Transforms/NewGVN/fence-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/fence.ll rename to llvm/test/Transforms/NewGVN/fence-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/invariant.group.ll b/llvm/test/Transforms/NewGVN/invariant.group-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/invariant.group.ll rename to llvm/test/Transforms/NewGVN/invariant.group-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/nonescaping-malloc.ll b/llvm/test/Transforms/NewGVN/nonescaping-malloc-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/nonescaping-malloc.ll rename to llvm/test/Transforms/NewGVN/nonescaping-malloc-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/opt-remarks.ll b/llvm/test/Transforms/NewGVN/opt-remarks-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/opt-remarks.ll rename to llvm/test/Transforms/NewGVN/opt-remarks-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/pr10820.ll b/llvm/test/Transforms/NewGVN/pr10820-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/pr10820.ll rename to llvm/test/Transforms/NewGVN/pr10820-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/pr14166.ll b/llvm/test/Transforms/NewGVN/pr14166-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/pr14166.ll rename to llvm/test/Transforms/NewGVN/pr14166-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/pre-new-inst.ll b/llvm/test/Transforms/NewGVN/pre-new-inst-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/pre-new-inst.ll rename to llvm/test/Transforms/NewGVN/pre-new-inst-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/rle-must-alias.ll b/llvm/test/Transforms/NewGVN/rle-must-alias-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/rle-must-alias.ll rename to llvm/test/Transforms/NewGVN/rle-must-alias-xfail.ll diff --git a/llvm/test/Transforms/NewGVN/rle-no-phi-translate.ll b/llvm/test/Transforms/NewGVN/rle-no-phi-translate-xfail.ll similarity index 100% rename from llvm/test/Transforms/NewGVN/rle-no-phi-translate.ll rename to llvm/test/Transforms/NewGVN/rle-no-phi-translate-xfail.ll From 4b626dd94944d60751af62d65a2692698520fcc2 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 13 Jul 2020 21:05:47 +0200 Subject: [PATCH 140/771] [NewGVN] Separate passing assume tests (NFC) Result might not be exactly the same as under GVN, but all the desired transforms are made. --- .../Transforms/NewGVN/assume-equal-xfail.ll | 111 ------------- llvm/test/Transforms/NewGVN/assume-equal.ll | 151 ++++++++++++++++++ 2 files changed, 151 insertions(+), 111 deletions(-) create mode 100644 llvm/test/Transforms/NewGVN/assume-equal.ll diff --git a/llvm/test/Transforms/NewGVN/assume-equal-xfail.ll b/llvm/test/Transforms/NewGVN/assume-equal-xfail.ll index 7e009192064a7..7da17441d0787 100644 --- a/llvm/test/Transforms/NewGVN/assume-equal-xfail.ll +++ b/llvm/test/Transforms/NewGVN/assume-equal-xfail.ll @@ -154,117 +154,6 @@ entry: ret float %0 } -; CHECK-LABEL: define float @_Z1if(float %p) -define float @_Z1if(float %p) { -entry: - %p.addr = alloca float, align 4 - store float %p, float* %p.addr, align 4 - - %0 = load float, float* %p.addr, align 4 - %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate - call void @llvm.assume(i1 %cmp) - - ; CHECK-NOT: ret float 3.000000e+00 - ret float %0 -} - -; This test checks if constant propagation works for multiple node edges -; CHECK-LABEL: define i32 @_Z1ii(i32 %p) -define i32 @_Z1ii(i32 %p) { -entry: - %cmp = icmp eq i32 %p, 42 - call void @llvm.assume(i1 %cmp) - - ; CHECK: br i1 true, label %bb2, label %bb2 - br i1 %cmp, label %bb2, label %bb2 -bb2: - call void @llvm.assume(i1 true) - ; CHECK: br i1 true, label %bb2, label %bb2 - br i1 %cmp, label %bb2, label %bb2 - - ; CHECK: ret i32 42 - ret i32 %p -} - -; CHECK-LABEL: define i32 @_Z1ij(i32 %p) -define i32 @_Z1ij(i32 %p) { -entry: - %cmp = icmp eq i32 %p, 42 - call void @llvm.assume(i1 %cmp) - - ; CHECK: br i1 true, label %bb2, label %bb2 - br i1 %cmp, label %bb2, label %bb2 -bb2: - ; CHECK-NOT: %cmp2 = - %cmp2 = icmp eq i32 %p, 42 - ; CHECK-NOT: call void @llvm.assume( - call void @llvm.assume(i1 %cmp2) - - ; CHECK: br i1 true, label %bb2, label %bb2 - br i1 %cmp, label %bb2, label %bb2 - - ; CHECK: ret i32 42 - ret i32 %p -} - -; CHECK-LABEL: define i32 @_Z1ik(i32 %p) -define i32 @_Z1ik(i32 %p) { -entry: - %cmp = icmp eq i32 %p, 42 - call void @llvm.assume(i1 %cmp) - - ; CHECK: br i1 true, label %bb2, label %bb3 - br i1 %cmp, label %bb2, label %bb3 -bb2: - ; CHECK-NOT: %cmp3 = - %cmp3 = icmp eq i32 %p, 43 - ; CHECK: store i8 undef, i8* null - call void @llvm.assume(i1 %cmp3) - ret i32 15 -bb3: - ret i32 17 -} - -; This test checks if GVN can do the constant propagation correctly -; when there are multiple uses of the same assume value in the -; basic block that has a loop back-edge pointing to itself. -; -; CHECK-LABEL: define i32 @_Z1il(i32 %val, i1 %k) -define i32 @_Z1il(i32 %val, i1 %k) { - br label %next - -next: -; CHECK: tail call void @llvm.assume(i1 %k) -; CHECK-NEXT: %cmp = icmp eq i32 %val, 50 - tail call void @llvm.assume(i1 %k) - tail call void @llvm.assume(i1 %k) - %cmp = icmp eq i32 %val, 50 - br i1 %cmp, label %next, label %meh - -meh: - ret i32 0 -} - -; This test checks if GVN can prevent the constant propagation correctly -; in the successor blocks that are not dominated by the basic block -; with the assume instruction. -; -; CHECK-LABEL: define i1 @_z1im(i32 %val, i1 %k, i1 %j) -define i1 @_z1im(i32 %val, i1 %k, i1 %j) { - br i1 %j, label %next, label %meh - -next: -; CHECK: tail call void @llvm.assume(i1 %k) -; CHECK-NEXT: br label %meh - tail call void @llvm.assume(i1 %k) - tail call void @llvm.assume(i1 %k) - br label %meh - -meh: -; CHECK: ret i1 %k - ret i1 %k -} - declare noalias i8* @_Znwm(i64) declare void @_ZN1AC1Ev(%struct.A*) declare void @llvm.assume(i1) diff --git a/llvm/test/Transforms/NewGVN/assume-equal.ll b/llvm/test/Transforms/NewGVN/assume-equal.ll new file mode 100644 index 0000000000000..a20075665882a --- /dev/null +++ b/llvm/test/Transforms/NewGVN/assume-equal.ll @@ -0,0 +1,151 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -newgvn -S | FileCheck %s + +define float @_Z1if(float %p) { +; CHECK-LABEL: @_Z1if( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[P_ADDR:%.*]] = alloca float, align 4 +; CHECK-NEXT: store float [[P:%.*]], float* [[P_ADDR]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq float [[P]], 3.000000e+00 +; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: ret float [[P]] +; +entry: + %p.addr = alloca float, align 4 + store float %p, float* %p.addr, align 4 + + %0 = load float, float* %p.addr, align 4 + %cmp = fcmp ueq float %0, 3.000000e+00 ; no nnan flag - can't propagate + call void @llvm.assume(i1 %cmp) + + ret float %0 +} + +; This test checks if constant propagation works for multiple node edges +define i32 @_Z1ii(i32 %p) { +; CHECK-LABEL: @_Z1ii( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P:%.*]], 42 +; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: br i1 true, label [[BB2]], label [[BB2]] +; CHECK: 0: +; CHECK-NEXT: store i8 undef, i8* null, align 1 +; CHECK-NEXT: ret i32 [[P]] +; +entry: + %cmp = icmp eq i32 %p, 42 + call void @llvm.assume(i1 %cmp) + + br i1 %cmp, label %bb2, label %bb2 +bb2: + call void @llvm.assume(i1 true) + br i1 %cmp, label %bb2, label %bb2 + + ret i32 %p +} + +define i32 @_Z1ij(i32 %p) { +; CHECK-LABEL: @_Z1ij( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P:%.*]], 42 +; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: br i1 true, label [[TMP0:%.*]], label [[BB2]] +; CHECK: 0: +; CHECK-NEXT: ret i32 42 +; +entry: + %cmp = icmp eq i32 %p, 42 + call void @llvm.assume(i1 %cmp) + + br i1 %cmp, label %bb2, label %bb2 +bb2: + %cmp2 = icmp eq i32 %p, 42 + call void @llvm.assume(i1 %cmp2) + + br i1 %cmp, label %0, label %bb2 + + ret i32 %p +} + +define i32 @_Z1ik(i32 %p) { +; CHECK-LABEL: @_Z1ik( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P:%.*]], 42 +; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[BB3:%.*]] +; CHECK: bb2: +; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: ret i32 15 +; CHECK: bb3: +; CHECK-NEXT: store i8 undef, i8* null, align 1 +; CHECK-NEXT: ret i32 17 +; +entry: + %cmp = icmp eq i32 %p, 42 + call void @llvm.assume(i1 %cmp) + + br i1 %cmp, label %bb2, label %bb3 +bb2: + %cmp3 = icmp eq i32 %p, 43 + call void @llvm.assume(i1 %cmp3) + ret i32 15 +bb3: + ret i32 17 +} + +; This test checks if GVN can do the constant propagation correctly +; when there are multiple uses of the same assume value in the +; basic block that has a loop back-edge pointing to itself. +define i32 @_Z1il(i32 %val, i1 %k) { +; CHECK-LABEL: @_Z1il( +; CHECK-NEXT: br label [[NEXT:%.*]] +; CHECK: next: +; CHECK-NEXT: tail call void @llvm.assume(i1 [[K:%.*]]) +; CHECK-NEXT: tail call void @llvm.assume(i1 [[K]]) +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[VAL:%.*]], 50 +; CHECK-NEXT: br i1 [[CMP]], label [[NEXT]], label [[MEH:%.*]] +; CHECK: meh: +; CHECK-NEXT: ret i32 0 +; + br label %next + +next: + tail call void @llvm.assume(i1 %k) + tail call void @llvm.assume(i1 %k) + %cmp = icmp eq i32 %val, 50 + br i1 %cmp, label %next, label %meh + +meh: + ret i32 0 +} + +; This test checks if GVN can prevent the constant propagation correctly +; in the successor blocks that are not dominated by the basic block +; with the assume instruction. +define i1 @_z1im(i32 %val, i1 %k, i1 %j) { +; CHECK-LABEL: @_z1im( +; CHECK-NEXT: br i1 [[J:%.*]], label [[NEXT:%.*]], label [[MEH:%.*]] +; CHECK: next: +; CHECK-NEXT: tail call void @llvm.assume(i1 [[K:%.*]]) +; CHECK-NEXT: tail call void @llvm.assume(i1 [[K]]) +; CHECK-NEXT: br label [[MEH]] +; CHECK: meh: +; CHECK-NEXT: ret i1 [[K]] +; + br i1 %j, label %next, label %meh + +next: + tail call void @llvm.assume(i1 %k) + tail call void @llvm.assume(i1 %k) + br label %meh + +meh: + ret i1 %k +} + +declare void @llvm.assume(i1) From 353fa4403a06c2d86d617362b42e20ee6b3f53be Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 11 Jul 2020 22:48:26 +0200 Subject: [PATCH 141/771] [PredicateInfo] Place predicate info after assume Place the ssa.copy instructions for assumes after the assume, instead of before it. Both options are valid, but placing them afterwards prevents assumes from being replaced with assume(true). This fixes https://bugs.llvm.org/show_bug.cgi?id=37541 in NewGVN and will avoid a similar issue in SCCP when we handle more predicate infos. Differential Revision: https://reviews.llvm.org/D83631 --- llvm/lib/Transforms/Utils/PredicateInfo.cpp | 10 +++++---- llvm/test/Transforms/NewGVN/assume-equal.ll | 10 ++++----- llvm/test/Transforms/NewGVN/assumes.ll | 4 ++-- .../Util/PredicateInfo/testandor.ll | 22 +++++++++---------- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp index c81efd77aa5ff..6ac2d64494e94 100644 --- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp +++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp @@ -205,14 +205,14 @@ struct ValueDFS_Compare { // numbering will say the placed predicaeinfos should go first (IE // LN_beginning), so we won't be in this function. For assumes, we will end // up here, beause we need to order the def we will place relative to the - // assume. So for the purpose of ordering, we pretend the def is the assume - // because that is where we will insert the info. + // assume. So for the purpose of ordering, we pretend the def is right + // after the assume, because that is where we will insert the info. if (!VD.U) { assert(VD.PInfo && "No def, no use, and no predicateinfo should not occur"); assert(isa(VD.PInfo) && "Middle of block should only occur for assumes"); - return cast(VD.PInfo)->AssumeInst; + return cast(VD.PInfo)->AssumeInst->getNextNode(); } return nullptr; } @@ -621,7 +621,9 @@ Value *PredicateInfoBuilder::materializeStack(unsigned int &Counter, auto *PAssume = dyn_cast(ValInfo); assert(PAssume && "Should not have gotten here without it being an assume"); - IRBuilder<> B(PAssume->AssumeInst); + // Insert the predicate directly after the assume. While it also holds + // directly before it, assume(i1 true) is not a useful fact. + IRBuilder<> B(PAssume->AssumeInst->getNextNode()); Function *IF = getCopyDeclaration(F.getParent(), Op->getType()); if (IF->users().empty()) PI.CreatedDeclarations.insert(IF); diff --git a/llvm/test/Transforms/NewGVN/assume-equal.ll b/llvm/test/Transforms/NewGVN/assume-equal.ll index a20075665882a..d67105fbf1a28 100644 --- a/llvm/test/Transforms/NewGVN/assume-equal.ll +++ b/llvm/test/Transforms/NewGVN/assume-equal.ll @@ -7,7 +7,7 @@ define float @_Z1if(float %p) { ; CHECK-NEXT: [[P_ADDR:%.*]] = alloca float, align 4 ; CHECK-NEXT: store float [[P:%.*]], float* [[P_ADDR]], align 4 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq float [[P]], 3.000000e+00 -; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: ret float [[P]] ; entry: @@ -26,7 +26,7 @@ define i32 @_Z1ii(i32 %p) { ; CHECK-LABEL: @_Z1ii( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P:%.*]], 42 -; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[BB2]] ; CHECK: bb2: ; CHECK-NEXT: br i1 true, label [[BB2]], label [[BB2]] @@ -50,7 +50,7 @@ define i32 @_Z1ij(i32 %p) { ; CHECK-LABEL: @_Z1ij( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P:%.*]], 42 -; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[BB2]] ; CHECK: bb2: ; CHECK-NEXT: call void @llvm.assume(i1 true) @@ -76,10 +76,10 @@ define i32 @_Z1ik(i32 %p) { ; CHECK-LABEL: @_Z1ik( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[P:%.*]], 42 -; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: br i1 true, label [[BB2:%.*]], label [[BB3:%.*]] ; CHECK: bb2: -; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: call void @llvm.assume(i1 false) ; CHECK-NEXT: ret i32 15 ; CHECK: bb3: ; CHECK-NEXT: store i8 undef, i8* null, align 1 diff --git a/llvm/test/Transforms/NewGVN/assumes.ll b/llvm/test/Transforms/NewGVN/assumes.ll index ea20b38bff6af..eee302a17ee46 100644 --- a/llvm/test/Transforms/NewGVN/assumes.ll +++ b/llvm/test/Transforms/NewGVN/assumes.ll @@ -4,7 +4,7 @@ define i32 @test1(i32 %arg) { ; CHECK-LABEL: @test1( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[ARG:%.*]], 5 -; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: ret i32 [[ARG]] ; %cmp = icmp sge i32 %arg, 5 @@ -18,7 +18,7 @@ define i32 @test2(i32 %arg, i1 %b) { ; CHECK: bb: ; CHECK-NEXT: [[A:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ 2, [[BB]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[ARG:%.*]], [[A]] -; CHECK-NEXT: call void @llvm.assume(i1 true) +; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: br i1 [[B:%.*]], label [[BB]], label [[END:%.*]] ; CHECK: end: ; CHECK-NEXT: ret i32 [[ARG]] diff --git a/llvm/test/Transforms/Util/PredicateInfo/testandor.ll b/llvm/test/Transforms/Util/PredicateInfo/testandor.ll index c84562cc5ef53..cd1491e31a8da 100644 --- a/llvm/test/Transforms/Util/PredicateInfo/testandor.ll +++ b/llvm/test/Transforms/Util/PredicateInfo/testandor.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -print-predicateinfo < %s 2>&1 | FileCheck %s +; RUN: opt -print-predicateinfo -disable-output < %s 2>&1 | FileCheck %s declare void @foo(i1) declare void @bar(i32) @@ -136,18 +136,18 @@ define void @testandassume(i32 %x, i32 %y) { ; CHECK-NEXT: [[XZ:%.*]] = icmp eq i32 [[X:%.*]], 0 ; CHECK-NEXT: [[YZ:%.*]] = icmp eq i32 [[Y:%.*]], 0 ; CHECK-NEXT: [[Z:%.*]] = and i1 [[XZ]], [[YZ]] -; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]]) -; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]]) +; CHECK-NEXT: call void @llvm.assume(i1 [[Z]]) +; CHECK: [[TMP1:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) +; CHECK: [[TMP2:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]]) ; CHECK: [[TMP3:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[YZ]]) -; CHECK: [[TMP4:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[Y]]) -; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[Z]]) -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP5]]) -; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP1]]) -; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP2]]) +; CHECK: [[TMP4:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[X]]) +; CHECK: [[TMP5:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[XZ]]) +; CHECK: [[DOT0:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP5]]) +; CHECK: [[DOT01:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP4]]) ; CHECK: [[DOT02:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP3]]) -; CHECK: [[DOT03:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP4]]) -; CHECK: [[DOT04:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP5]]) -; CHECK-NEXT: br i1 [[TMP5]], label [[BOTH:%.*]], label [[NOPE:%.*]] +; CHECK: [[DOT03:%.*]] = call i32 @llvm.ssa.copy.{{.+}}(i32 [[TMP2]]) +; CHECK: [[DOT04:%.*]] = call i1 @llvm.ssa.copy.{{.+}}(i1 [[TMP1]]) +; CHECK-NEXT: br i1 [[TMP1]], label [[BOTH:%.*]], label [[NOPE:%.*]] ; CHECK: both: ; CHECK-NEXT: call void @foo(i1 [[DOT0]]) ; CHECK-NEXT: call void @foo(i1 [[DOT02]]) From 3780d3eb1001fd25d4b4cf953ae621a0f3b30ee5 Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Mon, 13 Jul 2020 12:19:17 -0700 Subject: [PATCH 142/771] [flang] Use octal escapes for character literals in modfiles Character literals can be formatted using octal or hex escapes for non-ascii characters. This is so that the program can be unparsed for either pgf90 or gfortran to compile. But modfiles should not be affected by that -- they should be consistent. This changes causes modfiles to always have character literals formatted with octal escapes. Differential Revision: https://reviews.llvm.org/D83703 --- flang/lib/Semantics/mod-file.cpp | 4 ++++ flang/lib/Semantics/mod-file.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index 2f813d95f26b0..6fa59f0a82a08 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -8,6 +8,7 @@ #include "mod-file.h" #include "resolve-names.h" +#include "flang/Common/restorer.h" #include "flang/Evaluate/tools.h" #include "flang/Parser/message.h" #include "flang/Parser/parsing.h" @@ -99,6 +100,9 @@ class SubprogramSymbolCollector { }; bool ModFileWriter::WriteAll() { + // this flag affects character literals: force it to be consistent + auto restorer{ + common::ScopedSet(parser::useHexadecimalEscapeSequences, false)}; WriteAll(context_.globalScope()); return !context_.AnyFatalError(); } diff --git a/flang/lib/Semantics/mod-file.h b/flang/lib/Semantics/mod-file.h index 8823c5f1e4972..17ffe804c5be3 100644 --- a/flang/lib/Semantics/mod-file.h +++ b/flang/lib/Semantics/mod-file.h @@ -32,7 +32,7 @@ class SemanticsContext; class ModFileWriter { public: - ModFileWriter(SemanticsContext &context) : context_{context} {} + explicit ModFileWriter(SemanticsContext &context) : context_{context} {} bool WriteAll(); private: From 11046ef69e3e9ec3ae9f5f4caadf965b7f1e22c8 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Mon, 13 Jul 2020 12:14:21 -0700 Subject: [PATCH 143/771] [llvm][NFC] Factored the default inlining advice This is in preparation for the 'development' mode advisor. We currently want to track what the default policy's decision would have been, this refactoring makes it easier to do that. --- llvm/lib/Analysis/InlineAdvisor.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp index 9a3e5fa0df722..74a536d1ce2f4 100644 --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -84,7 +84,9 @@ class DefaultInlineAdvice : public InlineAdvice { } // namespace -std::unique_ptr DefaultInlineAdvisor::getAdvice(CallBase &CB) { +llvm::Optional +getDefaultInlineAdvice(CallBase &CB, FunctionAnalysisManager &FAM, + const InlineParams &Params) { Function &Caller = *CB.getCaller(); ProfileSummaryInfo *PSI = FAM.getResult(Caller) @@ -111,10 +113,16 @@ std::unique_ptr DefaultInlineAdvisor::getAdvice(CallBase &CB) { return getInlineCost(CB, Params, CalleeTTI, GetAssumptionCache, GetTLI, GetBFI, PSI, RemarksEnabled ? &ORE : nullptr); }; - auto OIC = llvm::shouldInline(CB, GetInlineCost, ORE, - Params.EnableDeferral.hasValue() && - Params.EnableDeferral.getValue()); - return std::make_unique(this, CB, OIC, ORE); + return llvm::shouldInline(CB, GetInlineCost, ORE, + Params.EnableDeferral.hasValue() && + Params.EnableDeferral.getValue()); +} + +std::unique_ptr DefaultInlineAdvisor::getAdvice(CallBase &CB) { + auto OIC = getDefaultInlineAdvice(CB, FAM, Params); + return std::make_unique( + this, CB, OIC, + FAM.getResult(*CB.getCaller())); } InlineAdvice::InlineAdvice(InlineAdvisor *Advisor, CallBase &CB, From 31b5b121299c08f360b61ecf873fe3eee99c0499 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 13 Jul 2020 12:37:18 -0700 Subject: [PATCH 144/771] [ORC] Remove a spurious reinterpret_cast. --- llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp index 5f89d91ef9948..18b3c5e12b1c2 100644 --- a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp +++ b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp @@ -461,9 +461,7 @@ void OrcI386::writeTrampolines(char *TrampolineWorkingMem, assert((ResolverAddr >> 32) == 0 && "ResolverAddr out of range"); uint64_t CallRelImm = 0xF1C4C400000000e8; - uint64_t ResolverRel = - ResolverAddr - reinterpret_cast(TrampolineBlockTargetAddress) - - 5; + uint64_t ResolverRel = ResolverAddr - TrampolineBlockTargetAddress - 5; uint64_t *Trampolines = reinterpret_cast(TrampolineWorkingMem); for (unsigned I = 0; I < NumTrampolines; ++I, ResolverRel -= TrampolineSize) From 340c376b87c72e7eb3670301e4920106615b6689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 13 Jul 2020 22:47:31 +0300 Subject: [PATCH 145/771] [lldb] Fix a CMake warning typo. NFC. --- lldb/tools/debugserver/source/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/tools/debugserver/source/CMakeLists.txt b/lldb/tools/debugserver/source/CMakeLists.txt index 9a7e2eb9a1a0f..b29b3ddc3056c 100644 --- a/lldb/tools/debugserver/source/CMakeLists.txt +++ b/lldb/tools/debugserver/source/CMakeLists.txt @@ -41,7 +41,7 @@ function(get_debugserver_codesign_identity result) return() endif() - message(WARNING "Development code sign identiy not found: 'lldb_codesign' ${not_found_help}") + message(WARNING "Development code sign identity not found: 'lldb_codesign' ${not_found_help}") # LLVM pendant: fallback if available if(LLVM_CODESIGNING_IDENTITY) From 341ec564182161861ec4415cdee1f4f3a0527e97 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Mon, 13 Jul 2020 13:09:53 -0700 Subject: [PATCH 146/771] Add a decorator to skip tests when running under Rosetta This allows skipping a test when running the testsuite on macOS under the Rosetta translation layer. Differential Revision: https://reviews.llvm.org/D83600 --- lldb/packages/Python/lldbsuite/test/decorators.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lldb/packages/Python/lldbsuite/test/decorators.py b/lldb/packages/Python/lldbsuite/test/decorators.py index ec084184cd656..be282f6db32c6 100644 --- a/lldb/packages/Python/lldbsuite/test/decorators.py +++ b/lldb/packages/Python/lldbsuite/test/decorators.py @@ -552,6 +552,14 @@ def are_sb_headers_missing(): return skipTestIfFn(are_sb_headers_missing)(func) +def skipIfRosetta(func, bugnumber=None): + """Skip a test when running the testsuite on macOS under the Rosetta translation layer.""" + def is_running_rosetta(self): + if not lldbplatformutil.getPlatform() in ['darwin', 'macosx']: + return False + return platform.uname()[5] == "arm" and self.getArchitecture() == "x86_64" + return skipTestIfFn(is_running_rosetta, bugnumber)(func) + def skipIfiOSSimulator(func): """Decorate the item to skip tests that should be skipped on the iOS Simulator.""" def is_ios_simulator(): From 9908a3b9f521c954cbf6adcec35b14b2f6c8da49 Mon Sep 17 00:00:00 2001 From: Davide Italiano Date: Mon, 13 Jul 2020 12:59:16 -0700 Subject: [PATCH 147/771] Revert "[llvm] Native size estimator for training -Oz inliner" This reverts commit 83080a294ad7d145d758821bcf4354ad0cb7d299 as it breaks the macOS modules build. --- llvm/CMakeLists.txt | 12 - .../Analysis/InlineSizeEstimatorAnalysis.h | 35 - llvm/include/llvm/Analysis/Utils/TFUtils.h | 136 - llvm/lib/Analysis/CMakeLists.txt | 40 +- .../Analysis/InlineSizeEstimatorAnalysis.cpp | 299 - llvm/lib/Analysis/TFUtils.cpp | 143 - llvm/lib/Passes/PassBuilder.cpp | 1 - llvm/lib/Passes/PassRegistry.def | 1 - llvm/unittests/Analysis/CMakeLists.txt | 12 +- .../InlineSizeEstimatorAnalysisTest.cpp | 101 - .../ir2native_x86_64_model/saved_model.pbtxt | 10596 ---------------- .../variables/variables.data-00000-of-00001 | Bin 88424 -> 0 bytes .../variables/variables.index | Bin 398 -> 0 bytes llvm/unittests/Analysis/TFUtilsTest.cpp | 98 - 14 files changed, 10 insertions(+), 11464 deletions(-) delete mode 100644 llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h delete mode 100644 llvm/include/llvm/Analysis/Utils/TFUtils.h delete mode 100644 llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp delete mode 100644 llvm/lib/Analysis/TFUtils.cpp delete mode 100644 llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp delete mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt delete mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001 delete mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index delete mode 100644 llvm/unittests/Analysis/TFUtilsTest.cpp diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 4e14e61fcacd6..de2887b64c2a9 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -981,18 +981,6 @@ if (NOT TENSORFLOW_AOT_PATH STREQUAL "") ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/tf_runtime) endif() -set(TENSORFLOW_C_LIB_PATH "" CACHE PATH "Path to TensorFlow C library install") -find_library(tensorflow_c_api tensorflow PATHS ${TENSORFLOW_C_LIB_PATH}/lib) - -# Similar to the above Tensorflow dependency, please refer to the same script. -# In this case, the latest C API library is available for download from -# https://www.tensorflow.org/install/lang_c -if (tensorflow_c_api) - set(LLVM_HAVE_TF_API "ON" CACHE BOOL "Full Tensorflow API available") - add_definitions("-DLLVM_HAVE_TF_API") - include_directories(${TENSORFLOW_C_LIB_PATH}/include) -endif() - # Put this before tblgen. Else we have a circular dependence. add_subdirectory(lib/Demangle) add_subdirectory(lib/Support) diff --git a/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h b/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h deleted file mode 100644 index 29a6f59146748..0000000000000 --- a/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h +++ /dev/null @@ -1,35 +0,0 @@ -//===- InlineSizeEstimatorAnalysis.h - ML size estimator --------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// - -#ifndef LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H -#define LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H - -#include "llvm/IR/PassManager.h" - -namespace llvm { -class Function; - -class TFModelEvaluator; -class InlineSizeEstimatorAnalysis - : public AnalysisInfoMixin { -public: - InlineSizeEstimatorAnalysis(); - InlineSizeEstimatorAnalysis(InlineSizeEstimatorAnalysis &&); - ~InlineSizeEstimatorAnalysis(); - - static AnalysisKey Key; - using Result = Optional; - Result run(const Function &F, FunctionAnalysisManager &FAM); - static bool isEvaluatorRequested(); - -private: - std::unique_ptr Evaluator; -}; -} // namespace llvm -#endif // LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H \ No newline at end of file diff --git a/llvm/include/llvm/Analysis/Utils/TFUtils.h b/llvm/include/llvm/Analysis/Utils/TFUtils.h deleted file mode 100644 index a1d7108b149ff..0000000000000 --- a/llvm/include/llvm/Analysis/Utils/TFUtils.h +++ /dev/null @@ -1,136 +0,0 @@ -//===- TFUtils.h - utilities for tensorflow C API ---------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -#ifndef LLVM_ANALYSIS_UTILS_TFUTILS_H -#define LLVM_ANALYSIS_UTILS_TFUTILS_H - -#include "tensorflow/c/c_api.h" -#include "llvm/IR/LLVMContext.h" - -#include -#include - -namespace llvm { - -/// Load a SavedModel, find the given inputs and outputs, and setup storage -/// for input tensors. The user is responsible for correctly dimensioning the -/// input tensors and setting their values before calling evaluate(). -/// To initialize: -/// - construct the object -/// - initialize the input tensors using initInput. Indices must correspond to -/// indices in the InputNames used at construction. -/// To use: -/// - set input values by using getInput to get each input tensor, and then -/// setting internal scalars, for all dimensions (tensors are row-major: -/// https://github.com/tensorflow/tensorflow/blob/r1.5/tensorflow/c/c_api.h#L205) -/// - prepare an output vector of TF_Output* type, with the correct number of -/// outputs (i.e. same as OutputNames). Initialize the vector with nullptr -/// values. -/// - call evaluate. The input tensors' values are not consumed after this, and -/// may still be read. -/// - use the outputs in the output vector -/// - deallocate each output tensor in the output vector, using TF_DeleteTensor. -class TFModelEvaluator final { -public: - /// The result of a model evaluation. Handles the lifetime of the output - /// TF_Tensor objects, which means that their values need to be used before - /// the EvaluationResult's dtor is called. - class EvaluationResult { - public: - ~EvaluationResult() { - for (auto *P : Output) - if (P) - TF_DeleteTensor(P); - } - - EvaluationResult(const EvaluationResult &) = delete; - EvaluationResult(EvaluationResult &&Other) - : OutputSize(Other.OutputSize), Output(std::move(Other.Output)) { - Other.Output.clear(); - }; - - /// Get a pointer to the first element of the tensor at Index. - template T *getTensorValue(size_t Index) { - return static_cast(TF_TensorData(Output[Index])); - } - - private: - friend class TFModelEvaluator; - EvaluationResult(size_t OutputSize) - : OutputSize(OutputSize), Output(OutputSize){}; - - const size_t OutputSize; - std::vector Output; - }; - - using TFGraphPtr = std::unique_ptr; - using TFSessionOptionsPtr = - std::unique_ptr; - using TFStatusPtr = std::unique_ptr; - - TFModelEvaluator(StringRef SavedModelPath, - const std::vector &InputNames, - const std::vector &OutputNames, - const char *Tags = "serve"); - ~TFModelEvaluator(); - TFModelEvaluator(const TFModelEvaluator &) = delete; - TFModelEvaluator(TFModelEvaluator &&) = delete; - - /// Evaluate the model, assuming it is valid. Returns None if the evaluation - /// fails or the model is invalid, or an EvaluationResult otherwise. The - /// inputs are assumed to have been already provided via getInput(). When - /// returning None, it also marks the object invalid. Pass an Output vector - /// with the same size as OutputNames, but with nullptr values. evaluate() - /// will populate it with tensors, matching in index the corresponding - /// OutputNames. The caller is responsible for the deallocation of those - /// tensors, using TF_DeleteTensor. - Optional evaluate(); - - /// Provides access to the input vector. It is already dimensioned correctly, - /// but the values need to be allocated by the user. - std::vector &getInput() { return Input; } - - /// Returns true if the tensorflow model was loaded successfully, false - /// otherwise. - bool isValid() const { return !!Session; } - - /// Initialize the input at Index as a tensor of the given type and dimensions - void initInput(int Index, TF_DataType Type, - const std::vector &Dimensions); - -private: - /// The objects necessary for carrying out an evaluation of the SavedModel. - /// They are expensive to set up, and we maintain them accross all the - /// evaluations of the model. - TF_Session *Session = nullptr; - TFGraphPtr Graph; - TFSessionOptionsPtr Options; - - /// The specification of the input nodes. - std::vector InputFeed; - - /// The input tensors. They must match by index of the corresponding InputFeed - /// value. We set up the tensors once and just mutate theirs scalars before - /// each evaluation. The input tensors keep their value after an evaluation. - std::vector Input; - - /// The specification of the output nodes. When evaluating, the tensors in the - /// output tensor vector must match by index the corresponding element in the - /// OutputFeed. - std::vector OutputFeed; - - /// Reusable utility for deleting the session. - void deleteSession(); - - /// Reusable utility for ensuring we can bind the requested Name to a node in - /// the SavedModel Graph. - bool checkReportAndReset(const TF_Output &Output, StringRef Name); -}; -} // namespace llvm - -#endif // LLVM_ANALYSIS_UTILS_TFUTILS_H \ No newline at end of file diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 703623396d96a..a317579ecc836 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -1,35 +1,17 @@ set(CommonMLSources MLInlineAdvisor.cpp) set(ReleaseModeMLSources ReleaseModeModelRunner.cpp) -set(DevelopmentModeMLSources TFUtils.cpp) -if (DEFINED LLVM_HAVE_TF_AOT OR DEFINED LLVM_HAVE_TF_API) - set(MLPolicySources ${CommonMLSources}) - if (DEFINED LLVM_HAVE_TF_AOT) - include(TensorFlowCompile) - tfcompile(models/inliner serve action InlinerSizeModel llvm::InlinerSizeModel) - list(APPEND ReleaseModeMLSources - $ - ${GENERATED_OBJS} - ) - LIST(APPEND MLPolicySources ${ReleaseModeMLSources}) - else() - LIST(APPEND LLVM_OPTIONAL_SOURCES ${ReleaseModeMLSources}) - endif() - - if (DEFINED LLVM_HAVE_TF_API) - LIST(APPEND MLPolicySources ${DevelopmentModeMLSources}) - LIST(APPEND MLLinkDeps ${tensorflow_c_api}) - else() - LIST(APPEND LLVM_OPTIONAL_SOURCES ${DevelopmentModeMLSources}) - endif() +if (DEFINED LLVM_HAVE_TF_AOT) + include(TensorFlowCompile) + tfcompile(models/inliner serve action InlinerSizeModel llvm::InlinerSizeModel) + list(APPEND ReleaseModeMLSources + $ + ${GENERATED_OBJS} + ) + set(MLPolicySources ${CommonMLSources} ${ReleaseModeMLSources}) else() - LIST(APPEND LLVM_OPTIONAL_SOURCES - ${CommonMLSources} - ${DevelopmentModeMLSources} - ${ReleaseModeMLSources} - ) + set(LLVM_OPTIONAL_SOURCES ${CommonMLSources} ${ReleaseModeMLSources}) endif() - add_llvm_component_library(LLVMAnalysis AliasAnalysis.cpp @@ -75,7 +57,6 @@ add_llvm_component_library(LLVMAnalysis InlineCost.cpp InlineAdvisor.cpp InlineFeaturesAnalysis.cpp - InlineSizeEstimatorAnalysis.cpp InstCount.cpp InstructionPrecedenceTracking.cpp InstructionSimplify.cpp @@ -143,7 +124,4 @@ add_llvm_component_library(LLVMAnalysis DEPENDS intrinsics_gen - - LINK_LIBS - ${MLLinkDeps} ) diff --git a/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp b/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp deleted file mode 100644 index 1d1952ae6cbbe..0000000000000 --- a/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp +++ /dev/null @@ -1,299 +0,0 @@ -//===- InlineSizeEstimatorAnalysis.cpp - IR to native size from ML model --===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This implements feature and label extraction for offline supervised learning -// of a IR to native size model. -// -//===----------------------------------------------------------------------===// -#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h" - -#ifdef LLVM_HAVE_TF_API -#include "llvm/Analysis/Utils/TFUtils.h" -#endif -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/PassManager.h" -#include "llvm/MC/MCAsmLayout.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/raw_ostream.h" - -#include -#include - -using namespace llvm; - -AnalysisKey InlineSizeEstimatorAnalysis::Key; - -#define DEBUG_TYPE "inline-size-estimator" - -#ifdef LLVM_HAVE_TF_API -cl::opt TFIR2NativeModelPath( - "ml-inliner-ir2native-model", cl::Hidden, - cl::desc("Path to saved model evaluating native size from IR.")); - -namespace { -unsigned getMaxInstructionID() { -#define LAST_OTHER_INST(NR) return NR; -#include "llvm/IR/Instruction.def" -} - -class IRToNativeSizeLearning { -public: - enum class NamedFeatureIndex : size_t { - InitialSize, - Blocks, - Calls, - IsLocal, - IsLinkOnceODR, - IsLinkOnce, - Loops, - MaxLoopDepth, - MaxDomTreeLevel, - - NumNamedFeatures - }; - static const size_t NumNamedFeatures = - static_cast(NamedFeatureIndex::NumNamedFeatures); - struct FunctionFeatures { - static std::vector> - ImportantInstructionSuccessions; - static const size_t FeatureCount; - - std::array NamedFeatures = {0}; - std::vector InstructionHistogram; - std::vector InstructionPairHistogram; - - void fillTensor(int32_t *Ptr) const; - int32_t &operator[](NamedFeatureIndex Pos) { - return NamedFeatures[static_cast(Pos)]; - } - }; - IRToNativeSizeLearning() = default; - - static FunctionFeatures getFunctionFeatures(Function &F, - FunctionAnalysisManager &FAM); - -private: - /// Sort once the feature tuples. - struct SortFeatureTuples { - bool IsSorted = false; - SortFeatureTuples() { - std::sort(FunctionFeatures::ImportantInstructionSuccessions.begin(), - FunctionFeatures::ImportantInstructionSuccessions.end()); - IsSorted = true; - } - }; - - static llvm::ManagedStatic TupleSorter; - - static bool ensureSortedTuples() { return TupleSorter->IsSorted; } -}; -llvm::ManagedStatic - IRToNativeSizeLearning::TupleSorter; - -// This is a point in time - we determined including these pairs of -// consecutive instructions (in the IR layout available at inline time) as -// features improves the model performance. We want to move away from manual -// feature selection. -// The vector is given in opcode pairs rather than labels because 1) labels -// weren't readily available, and 2) the successions were hand - extracted -std::vector> - IRToNativeSizeLearning::FunctionFeatures::ImportantInstructionSuccessions = - {{1, 34}, {15, 27}, {53, 53}, {53, 34}, {1, 11}, {32, 2}, {2, 48}, - {28, 48}, {1, 45}, {49, 32}, {57, 56}, {55, 53}, {1, 28}, {57, 34}, - {1, 1}, {32, 28}, {32, 15}, {49, 28}, {53, 1}, {2, 53}, {48, 34}, - {28, 53}, {2, 32}, {1, 40}, {32, 48}, {29, 56}, {56, 32}, {55, 56}, - {48, 56}, {1, 31}, {33, 34}, {2, 28}, {1, 12}, {55, 1}, {31, 31}, - {65, 1}, {33, 56}, {32, 32}, {13, 13}, {1, 26}, {13, 26}, {2, 1}, - {1, 33}, {47, 49}, {64, 1}, {2, 38}, {34, 53}, {48, 2}, {55, 34}, - {34, 32}, {1, 5}, {56, 13}, {2, 2}, {2, 49}, {33, 2}, {49, 39}, - {56, 49}, {33, 49}, {32, 39}, {39, 57}, {29, 33}, {31, 34}, {32, 29}, - {47, 15}, {13, 34}, {2, 33}, {32, 49}, {49, 34}, {56, 33}, {1, 30}, - {33, 33}, {31, 33}, {2, 29}, {56, 7}, {32, 13}, {2, 55}, {56, 56}, - {2, 34}, {1, 42}, {34, 49}, {1, 20}, {32, 33}, {1, 25}, {53, 28}, - {1, 14}, {31, 49}, {28, 2}, {2, 13}, {2, 56}, {1, 32}, {56, 53}, - {65, 65}, {33, 53}, {64, 64}, {13, 2}, {34, 33}, {1, 4}, {49, 2}, - {1, 9}, {56, 1}, {33, 1}, {53, 57}, {32, 53}, {13, 56}, {32, 56}, - {55, 55}, {1, 18}, {49, 56}, {34, 34}, {1, 7}, {56, 64}, {32, 1}, - {13, 33}, {55, 28}, {49, 33}, {57, 57}, {56, 34}, {34, 56}, {33, 32}, - {32, 40}, {1, 29}, {53, 2}, {34, 1}, {32, 34}, {49, 49}, {1, 24}, - {40, 34}, {1, 13}, {38, 34}, {29, 2}, {34, 2}, {1, 39}, {1, 22}, - {1, 27}, {49, 1}, {1, 8}, {56, 2}}; - -// We have: 9 calculated features (the features here); 1 feature for each -// instruction opcode; and 1 feature for each manually-identified sequence. -// For the latter 2, we build a histogram: we count the number of -// occurrences of each instruction opcode or succession of instructions, -// respectively. -// Note that instruction opcodes start from 1. For convenience, we also have an -// always 0 feature for the '0' opcode, hence the extra 1. -const size_t IRToNativeSizeLearning::FunctionFeatures::FeatureCount = - IRToNativeSizeLearning::FunctionFeatures::ImportantInstructionSuccessions - .size() + - getMaxInstructionID() + 1 + IRToNativeSizeLearning::NumNamedFeatures; - -size_t getSize(Function &F, TargetTransformInfo &TTI) { - size_t Ret = 0; - for (auto &BB : F) - for (auto &I : BB) - Ret += TTI.getInstructionCost( - &I, TargetTransformInfo::TargetCostKind::TCK_CodeSize); - return Ret; -} - -size_t getSize(Function &F, FunctionAnalysisManager &FAM) { - auto &TTI = FAM.getResult(F); - return getSize(F, TTI); -} - -unsigned getMaxDominatorTreeDepth(const Function &F, - const DominatorTree &Tree) { - unsigned Ret = 0; - for (auto &BB : F) - if (auto *TN = Tree.getNode(&BB)) - Ret = std::max(Ret, TN->getLevel()); - return Ret; -} -} // namespace - -IRToNativeSizeLearning::FunctionFeatures -IRToNativeSizeLearning::getFunctionFeatures(Function &F, - FunctionAnalysisManager &FAM) { - assert(ensureSortedTuples() && "expected lazy initialization"); - - auto &DomTree = FAM.getResult(F); - FunctionFeatures FF; - size_t InstrCount = getMaxInstructionID() + 1; - FF.InstructionHistogram.resize(InstrCount); - - FF.InstructionPairHistogram.resize( - FunctionFeatures::ImportantInstructionSuccessions.size()); - - auto StartID = 0; - auto LastID = StartID; - auto getPairIndex = [](size_t a, size_t b) { - auto I = - std::find(FunctionFeatures::ImportantInstructionSuccessions.begin(), - FunctionFeatures::ImportantInstructionSuccessions.end(), - std::make_pair(a, b)); - if (I == FunctionFeatures::ImportantInstructionSuccessions.end()) - return -1; - return static_cast(std::distance( - FunctionFeatures::ImportantInstructionSuccessions.begin(), I)); - }; - - // We don't want debug calls, because they'd just add noise. - for (auto &BB : F) { - for (auto I = BB.instructionsWithoutDebug().begin(), - E = BB.instructionsWithoutDebug().end(); - I != E; ++I) { - auto ID = I->getOpcode(); - - ++FF.InstructionHistogram[ID]; - int PairIndex = getPairIndex(LastID, ID); - if (PairIndex >= 0) - ++FF.InstructionPairHistogram[PairIndex]; - LastID = ID; - if (isa(*I)) - ++FF[NamedFeatureIndex::Calls]; - } - } - - FF[NamedFeatureIndex::InitialSize] = getSize(F, FAM); - FF[NamedFeatureIndex::IsLocal] = F.hasLocalLinkage(); - FF[NamedFeatureIndex::IsLinkOnceODR] = F.hasLinkOnceODRLinkage(); - FF[NamedFeatureIndex::IsLinkOnce] = F.hasLinkOnceLinkage(); - FF[NamedFeatureIndex::Blocks] = - std::distance(F.getBasicBlockList().begin(), F.getBasicBlockList().end()); - auto &LI = FAM.getResult(F); - FF[NamedFeatureIndex::Loops] = std::distance(LI.begin(), LI.end()); - for (auto &L : LI) - FF[NamedFeatureIndex::MaxLoopDepth] = - std::max(FF[NamedFeatureIndex::MaxLoopDepth], - static_cast(L->getLoopDepth())); - FF[NamedFeatureIndex::MaxDomTreeLevel] = getMaxDominatorTreeDepth(F, DomTree); - return FF; -} - -void IRToNativeSizeLearning::FunctionFeatures::fillTensor(int32_t *Ptr) const { - std::copy(NamedFeatures.begin(), NamedFeatures.end(), Ptr); - Ptr += NamedFeatures.size(); - std::copy(InstructionHistogram.begin(), InstructionHistogram.end(), Ptr); - Ptr += InstructionHistogram.size(); - std::copy(InstructionPairHistogram.begin(), InstructionPairHistogram.end(), - Ptr); -} - -bool InlineSizeEstimatorAnalysis::isEvaluatorRequested() { - return !TFIR2NativeModelPath.empty(); -} - -InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis() { - if (!isEvaluatorRequested()) { - return; - } - std::vector InputNames{"serving_default_input_1"}; - std::vector OutputName{"StatefulPartitionedCall"}; - Evaluator = std::make_unique( - TFIR2NativeModelPath.getValue().c_str(), InputNames, OutputName); - if (!Evaluator || !Evaluator->isValid()) { - Evaluator.reset(); - return; - } - static const std::vector Dim{ - 1, static_cast( - IRToNativeSizeLearning::FunctionFeatures::FeatureCount)}; - - Evaluator->initInput(0, TF_INT32, Dim); -} - -InlineSizeEstimatorAnalysis::Result -InlineSizeEstimatorAnalysis::run(const Function &F, - FunctionAnalysisManager &FAM) { - if (!Evaluator) - return None; - auto Features = IRToNativeSizeLearning::getFunctionFeatures( - const_cast(F), FAM); - int32_t *V = static_cast(TF_TensorData(Evaluator->getInput()[0])); - Features.fillTensor(V); - auto ER = Evaluator->evaluate(); - if (!ER) - return None; - float Ret = *ER->getTensorValue(0); - if (Ret < 0.0) - Ret = 0.0; - return static_cast(Ret); -} - -InlineSizeEstimatorAnalysis::~InlineSizeEstimatorAnalysis() {} -InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis( - InlineSizeEstimatorAnalysis &&Other) - : Evaluator(std::move(Other.Evaluator)) {} - -#else -namespace llvm { -class TFModelEvaluator {}; -} // namespace llvm -InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis() {} -InlineSizeEstimatorAnalysis ::InlineSizeEstimatorAnalysis( - InlineSizeEstimatorAnalysis &&) {} -InlineSizeEstimatorAnalysis::~InlineSizeEstimatorAnalysis() {} -InlineSizeEstimatorAnalysis::Result -InlineSizeEstimatorAnalysis::run(const Function &F, - FunctionAnalysisManager &FAM) { - return None; -} -bool InlineSizeEstimatorAnalysis::isEvaluatorRequested() { return false; } -#endif \ No newline at end of file diff --git a/llvm/lib/Analysis/TFUtils.cpp b/llvm/lib/Analysis/TFUtils.cpp deleted file mode 100644 index 6cd5b5c9b4eae..0000000000000 --- a/llvm/lib/Analysis/TFUtils.cpp +++ /dev/null @@ -1,143 +0,0 @@ -//===- TFUtils.cpp - tensorflow evaluation utilities ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements utilities for interfacing with tensorflow C APIs. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/Utils/TFUtils.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/raw_ostream.h" - -#include "tensorflow/c/c_api_experimental.h" - -#include - -using namespace llvm; - -namespace { - -struct TFInitializer { - TFInitializer() { - assert(!IsInitialized && "TFInitialized should be called only once"); - int Argc = 1; - const char *Name = ""; - const char **NamePtr = &Name; - TF_InitMain(Name, &Argc, const_cast(&NamePtr)); - IsInitialized = true; - } - bool IsInitialized = false; -}; - -llvm::ManagedStatic TFLibInitializer; - -bool ensureInitTF() { return TFLibInitializer->IsInitialized; } - -TFModelEvaluator::TFGraphPtr createTFGraph() { - return TFModelEvaluator::TFGraphPtr(TF_NewGraph(), &TF_DeleteGraph); -} - -TFModelEvaluator::TFStatusPtr createTFStatus() { - return TFModelEvaluator::TFStatusPtr(TF_NewStatus(), &TF_DeleteStatus); -} - -TFModelEvaluator::TFSessionOptionsPtr createTFSessionOptions() { - return TFModelEvaluator::TFSessionOptionsPtr(TF_NewSessionOptions(), - &TF_DeleteSessionOptions); -} -} // namespace - -TFModelEvaluator::TFModelEvaluator(StringRef SavedModelPath, - const std::vector &InputNames, - const std::vector &OutputNames, - const char *Tags) - : Graph(createTFGraph()), Options(createTFSessionOptions()), - InputFeed(InputNames.size()), Input(InputNames.size()), - OutputFeed(OutputNames.size()) { - if (!ensureInitTF()) { - errs() << "Tensorflow should have been initialized"; - return; - } - auto Status = createTFStatus(); - - Session = TF_LoadSessionFromSavedModel(Options.get(), nullptr, - SavedModelPath.str().c_str(), &Tags, 1, - Graph.get(), nullptr, Status.get()); - if (TF_GetCode(Status.get()) != TF_Code::TF_OK) { - errs() << TF_Message(Status.get()); - deleteSession(); - } - for (size_t I = 0; I < InputNames.size(); ++I) { - InputFeed[I] = { - TF_GraphOperationByName(Graph.get(), (InputNames[I]).c_str()), 0}; - if (!checkReportAndReset(InputFeed[I], InputNames[I])) - return; - } - for (size_t I = 0; I < OutputNames.size(); ++I) { - OutputFeed[I] = { - TF_GraphOperationByName(Graph.get(), (OutputNames[I]).c_str()), 0}; - if (!checkReportAndReset(OutputFeed[I], OutputNames[I])) - return; - } -} - -TFModelEvaluator::~TFModelEvaluator() { - for (auto *T : Input) { - TF_DeleteTensor(T); - } - deleteSession(); -} - -bool TFModelEvaluator::checkReportAndReset(const TF_Output &Output, - StringRef Name) { - if (Output.oper) - return true; - errs() << "Could not find TF_Output named: " + Name; - deleteSession(); - return false; -} - -void TFModelEvaluator::deleteSession() { - if (Session == nullptr) - return; - auto Status = createTFStatus(); - TF_DeleteSession(Session, Status.get()); - Session = nullptr; - if (TF_GetCode(Status.get()) != TF_Code::TF_OK) - errs() << "Could not delete TF session"; -} - -Optional TFModelEvaluator::evaluate() { - if (!isValid()) - return None; - EvaluationResult Ret(OutputFeed.size()); - auto Status = createTFStatus(); - TF_SessionRun(Session, nullptr, InputFeed.data(), Input.data(), Input.size(), - OutputFeed.data(), Ret.Output.data(), Ret.Output.size(), - nullptr, 0, nullptr, Status.get()); - if (TF_GetCode(Status.get()) != TF_Code::TF_OK) { - errs() << TF_Message(Status.get()); - deleteSession(); - return None; - } - return Ret; -} - -void TFModelEvaluator::initInput(int Index, TF_DataType Type, - const std::vector &Dimensions) { - int64_t TotalSize = TF_DataTypeSize(Type); - for (auto &D : Dimensions) - TotalSize *= D; - - Input[Index] = - TF_AllocateTensor(Type, Dimensions.data(), Dimensions.size(), TotalSize); - std::memset(TF_TensorData(Input[Index]), 0, TotalSize); -} \ No newline at end of file diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 537d300fee557..53158e7aabab0 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -35,7 +35,6 @@ #include "llvm/Analysis/IVUsers.h" #include "llvm/Analysis/InlineAdvisor.h" #include "llvm/Analysis/InlineFeaturesAnalysis.h" -#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LazyValueInfo.h" #include "llvm/Analysis/LoopAccessAnalysis.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index dfdfc3d05976a..eb2b740db5612 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -133,7 +133,6 @@ FUNCTION_ANALYSIS("loops", LoopAnalysis()) FUNCTION_ANALYSIS("lazy-value-info", LazyValueAnalysis()) FUNCTION_ANALYSIS("da", DependenceAnalysis()) FUNCTION_ANALYSIS("inliner-features", InlineFeaturesAnalysis()) -FUNCTION_ANALYSIS("inliner-size-estimator", InlineSizeEstimatorAnalysis()) FUNCTION_ANALYSIS("memdep", MemoryDependenceAnalysis()) FUNCTION_ANALYSIS("memoryssa", MemorySSAAnalysis()) FUNCTION_ANALYSIS("phi-values", PhiValuesAnalysis()) diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt index 59ad444d32fb4..42f7dd3c06101 100644 --- a/llvm/unittests/Analysis/CMakeLists.txt +++ b/llvm/unittests/Analysis/CMakeLists.txt @@ -6,13 +6,7 @@ set(LLVM_LINK_COMPONENTS TransformUtils ) -if (DEFINED LLVM_HAVE_TF_API) - LIST(APPEND EXTRA_TESTS TFUtilsTest.cpp) -else() - LIST(APPEND LLVM_OPTIONAL_SOURCES TFUtilsTest.cpp) -endif() - -add_llvm_unittest_with_input_files(AnalysisTests +add_llvm_unittest(AnalysisTests AliasAnalysisTest.cpp AliasSetTrackerTest.cpp AssumeBundleQueriesTest.cpp @@ -28,7 +22,6 @@ add_llvm_unittest_with_input_files(AnalysisTests DomTreeUpdaterTest.cpp GlobalsModRefTest.cpp InlineFeaturesAnalysisTest.cpp - InlineSizeEstimatorAnalysisTest.cpp IVDescriptorsTest.cpp LazyCallGraphTest.cpp LoadsTest.cpp @@ -47,7 +40,4 @@ add_llvm_unittest_with_input_files(AnalysisTests ValueLatticeTest.cpp ValueTrackingTest.cpp VectorUtilsTest.cpp - ${EXTRA_TESTS} ) - - target_link_libraries(AnalysisTests PRIVATE LLVMTestingSupport) diff --git a/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp b/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp deleted file mode 100644 index 377590be016ac..0000000000000 --- a/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp +++ /dev/null @@ -1,101 +0,0 @@ -//===- InlineSizeEstimatorAnalysisTest.cpp - test for ir2native -----------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/IR/Dominators.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Testing/Support/SupportHelpers.h" -#include "gtest/gtest.h" - -using namespace llvm; - -extern const char *TestMainArgv0; -extern cl::opt TFIR2NativeModelPath; - -#if LLVM_HAVE_TF_API -static std::string getModelPath() { - SmallString<128> InputsDir = unittest::getInputFileDirectory(TestMainArgv0); - llvm::sys::path::append(InputsDir, "ir2native_x86_64_model"); - return std::string(InputsDir); -} -#endif - -static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { - SMDiagnostic Err; - std::unique_ptr Mod = parseAssemblyString(IR, Err, C); - if (!Mod) - Err.print("MLAnalysisTests", errs()); - return Mod; -} - -static FunctionAnalysisManager buildFAM() { - FunctionAnalysisManager FAM; - FAM.registerPass([&] { return DominatorTreeAnalysis(); }); - FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); - FAM.registerPass([&] { return TargetIRAnalysis(); }); - FAM.registerPass([&] { return LoopAnalysis(); }); - return FAM; -} - -// Test model loading and evaluation. -TEST(InlineSizeEstimatorAnalysis, SizeIsValidTest) { - LLVMContext C; - std::unique_ptr M = parseIR(C, - R"IR( -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-linux-gnu" - -declare i32 @f1(i32) -declare i32 @f2(i32) - -define i32 @branches(i32) { - %cond = icmp slt i32 %0, 3 - br i1 %cond, label %then, label %else - -then: - %ret.1 = call i32 @f1(i32 %0) - br label %last.block - -else: - %ret.2 = call i32 @f2(i32 %0) - br label %last.block - -last.block: - %ret = phi i32 [%ret.1, %then], [%ret.2, %else] - ret i32 %ret -} - -define internal i32 @top() { - %1 = call i32 @branches(i32 2) - %2 = call i32 @f1(i32 %1) - ret i32 %2 -} -)IR"); - - FunctionAnalysisManager FAM = buildFAM(); -#if LLVM_HAVE_TF_API - TFIR2NativeModelPath = getModelPath(); -#endif - - InlineSizeEstimatorAnalysis FA; - auto SizeEstimate = FA.run(*M->getFunction("branches"), FAM); -#if LLVM_HAVE_TF_API - EXPECT_GT(*SizeEstimate, 0); -#else - EXPECT_FALSE(SizeEstimate.hasValue()); -#endif -} diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt deleted file mode 100644 index 6efdad51083d3..0000000000000 --- a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt +++ /dev/null @@ -1,10596 +0,0 @@ -saved_model_schema_version: 1 -meta_graphs { - meta_info_def { - stripped_op_list { - op { - name: "Const" - output_arg { - name: "output" - type_attr: "dtype" - } - attr { - name: "value" - type: "tensor" - } - attr { - name: "dtype" - type: "type" - } - } - op { - name: "NoOp" - } - op { - name: "Placeholder" - output_arg { - name: "output" - type_attr: "dtype" - } - attr { - name: "dtype" - type: "type" - } - attr { - name: "shape" - type: "shape" - default_value { - shape { - unknown_rank: true - } - } - } - } - op { - name: "ReadVariableOp" - input_arg { - name: "resource" - type: DT_RESOURCE - } - output_arg { - name: "value" - type_attr: "dtype" - } - attr { - name: "dtype" - type: "type" - } - is_stateful: true - } - op { - name: "StatefulPartitionedCall" - input_arg { - name: "args" - type_list_attr: "Tin" - } - output_arg { - name: "output" - type_list_attr: "Tout" - } - attr { - name: "Tin" - type: "list(type)" - has_minimum: true - } - attr { - name: "Tout" - type: "list(type)" - has_minimum: true - } - attr { - name: "f" - type: "func" - } - attr { - name: "config" - type: "string" - default_value { - s: "" - } - } - attr { - name: "config_proto" - type: "string" - default_value { - s: "" - } - } - attr { - name: "executor_type" - type: "string" - default_value { - s: "" - } - } - is_stateful: true - } - op { - name: "VarHandleOp" - output_arg { - name: "resource" - type: DT_RESOURCE - } - attr { - name: "container" - type: "string" - default_value { - s: "" - } - } - attr { - name: "shared_name" - type: "string" - default_value { - s: "" - } - } - attr { - name: "dtype" - type: "type" - } - attr { - name: "shape" - type: "shape" - } - is_stateful: true - } - } - tags: "serve" - tensorflow_version: "1.15.0" - tensorflow_git_version: "unknown" - stripped_default_attrs: true - } - graph_def { - node { - name: "dense/kernel" - op: "VarHandleOp" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - attr { - key: "shape" - value { - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - } - } - attr { - key: "shared_name" - value { - s: "dense/kernel" - } - } - } - node { - name: "dense/kernel/Read/ReadVariableOp" - op: "ReadVariableOp" - input: "dense/kernel" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - } - node { - name: "dense/bias" - op: "VarHandleOp" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - attr { - key: "shape" - value { - shape { - dim { - size: 100 - } - } - } - } - attr { - key: "shared_name" - value { - s: "dense/bias" - } - } - } - node { - name: "dense/bias/Read/ReadVariableOp" - op: "ReadVariableOp" - input: "dense/bias" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - } - node { - name: "dense_1/kernel" - op: "VarHandleOp" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - attr { - key: "shape" - value { - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - } - } - attr { - key: "shared_name" - value { - s: "dense_1/kernel" - } - } - } - node { - name: "dense_1/kernel/Read/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_1/kernel" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - } - node { - name: "dense_1/bias" - op: "VarHandleOp" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - attr { - key: "shape" - value { - shape { - dim { - size: 1 - } - } - } - } - attr { - key: "shared_name" - value { - s: "dense_1/bias" - } - } - } - node { - name: "dense_1/bias/Read/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_1/bias" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - } - node { - name: "total" - op: "VarHandleOp" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - attr { - key: "shape" - value { - shape { - } - } - } - attr { - key: "shared_name" - value { - s: "total" - } - } - } - node { - name: "total/Read/ReadVariableOp" - op: "ReadVariableOp" - input: "total" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - } - node { - name: "count" - op: "VarHandleOp" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - attr { - key: "shape" - value { - shape { - } - } - } - attr { - key: "shared_name" - value { - s: "count" - } - } - } - node { - name: "count/Read/ReadVariableOp" - op: "ReadVariableOp" - input: "count" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - } - node { - name: "total_1" - op: "VarHandleOp" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - attr { - key: "shape" - value { - shape { - } - } - } - attr { - key: "shared_name" - value { - s: "total_1" - } - } - } - node { - name: "total_1/Read/ReadVariableOp" - op: "ReadVariableOp" - input: "total_1" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - } - node { - name: "count_1" - op: "VarHandleOp" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - attr { - key: "shape" - value { - shape { - } - } - } - attr { - key: "shared_name" - value { - s: "count_1" - } - } - } - node { - name: "count_1/Read/ReadVariableOp" - op: "ReadVariableOp" - input: "count_1" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - } - node { - name: "NoOp" - op: "NoOp" - } - node { - name: "Const" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - } - string_val: "\n\277\001\n\030\010\001\022\024layer_with_weights-0\n\013\010\001\022\007layer-0\n\030\010\002\022\024layer_with_weights-1\n\013\010\002\022\007layer-1\n\r\010\003\022\toptimizer\n\031\010\004\022\025regularization_losses\n\r\010\005\022\tvariables\n\027\010\006\022\023trainable_variables\n\r\010\007\022\tkeras_api\n\016\010\010\022\nsignatures\nh\n\n\010\t\022\006kernel\n\010\010\n\022\004bias\n\031\010\013\022\025regularization_losses\n\r\010\014\022\tvariables\n\027\010\r\022\023trainable_variables\n\r\010\016\022\tkeras_api\nh\n\n\010\017\022\006kernel\n\010\010\020\022\004bias\n\031\010\021\022\025regularization_losses\n\r\010\022\022\tvariables\n\027\010\023\022\023trainable_variables\n\r\010\024\022\tkeras_api\n\000\n\000\n\034\n\005\010\t\022\0010\n\005\010\n\022\0011\n\005\010\017\022\0012\n\005\010\020\022\0013\n\034\n\005\010\t\022\0010\n\005\010\n\022\0011\n\005\010\017\022\0012\n\005\010\020\022\0013\n\255\001\n\n\010\025\022\006layers\n\037\010\026\022\033layer_regularization_losses\n\033\010\027\022\027non_trainable_variables\n\021\010\030\022\rlayer_metrics\n\031\010\004\022\025regularization_losses\n\013\010\031\022\007metrics\n\r\010\005\022\tvariables\n\027\010\006\022\023trainable_variables\n\000\nX\022V\n\016VARIABLE_VALUE\022\014dense/kernel\0326layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE\nT\022R\n\016VARIABLE_VALUE\022\ndense/bias\0324layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010\t\022\0010\n\005\010\n\022\0011\n\016\n\005\010\t\022\0010\n\005\010\n\022\0011\n\255\001\n\n\010\032\022\006layers\n\037\010\033\022\033layer_regularization_losses\n\033\010\034\022\027non_trainable_variables\n\021\010\035\022\rlayer_metrics\n\031\010\013\022\025regularization_losses\n\013\010\036\022\007metrics\n\r\010\014\022\tvariables\n\027\010\r\022\023trainable_variables\nZ\022X\n\016VARIABLE_VALUE\022\016dense_1/kernel\0326layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE\nV\022T\n\016VARIABLE_VALUE\022\014dense_1/bias\0324layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010\017\022\0010\n\005\010\020\022\0011\n\016\n\005\010\017\022\0010\n\005\010\020\022\0011\n\255\001\n\n\010\037\022\006layers\n\037\010 \022\033layer_regularization_losses\n\033\010!\022\027non_trainable_variables\n\021\010\"\022\rlayer_metrics\n\031\010\021\022\025regularization_losses\n\013\010#\022\007metrics\n\r\010\022\022\tvariables\n\027\010\023\022\023trainable_variables\n\016\n\005\010\001\022\0010\n\005\010\002\022\0011\n\000\n\000\n\000\n\016\n\005\010$\022\0010\n\005\010%\022\0011\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n4\n\t\010&\022\005total\n\t\010\'\022\005count\n\r\010(\022\tvariables\n\r\010)\022\tkeras_api\nD\n\t\010*\022\005total\n\t\010+\022\005count\n\016\010,\022\n_fn_kwargs\n\r\010-\022\tvariables\n\r\010.\022\tkeras_api\nO\022M\n\016VARIABLE_VALUE\022\005total\0324keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE\nO\022M\n\016VARIABLE_VALUE\022\005count\0324keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE\n\016\n\005\010&\022\0010\n\005\010\'\022\0011\n\017\n\r\010(\022\tvariables\nQ\022O\n\016VARIABLE_VALUE\022\007total_1\0324keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE\nQ\022O\n\016VARIABLE_VALUE\022\007count_1\0324keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010*\022\0010\n\005\010+\022\0011\n\017\n\r\010-\022\tvariables" - } - } - } - } - node { - name: "serving_default_input_1" - op: "Placeholder" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_INT32 - } - } - attr { - key: "shape" - value { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - node { - name: "StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "serving_default_input_1" - input: "dense/kernel" - input: "dense/bias" - input: "dense_1/kernel" - input: "dense_1/bias" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - i: 3 - i: 4 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_signature_wrapper_6671" - } - } - } - } - node { - name: "saver_filename" - op: "Placeholder" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "shape" - value { - shape { - } - } - } - } - node { - name: "StatefulPartitionedCall_1" - op: "StatefulPartitionedCall" - input: "saver_filename" - input: "dense/kernel/Read/ReadVariableOp" - input: "dense/bias/Read/ReadVariableOp" - input: "dense_1/kernel/Read/ReadVariableOp" - input: "dense_1/bias/Read/ReadVariableOp" - input: "total/Read/ReadVariableOp" - input: "count/Read/ReadVariableOp" - input: "total_1/Read/ReadVariableOp" - input: "count_1/Read/ReadVariableOp" - input: "Const" - attr { - key: "Tin" - value { - list { - type: DT_STRING - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_STRING - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_STRING - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference__traced_save_6824" - } - } - } - } - node { - name: "StatefulPartitionedCall_2" - op: "StatefulPartitionedCall" - input: "saver_filename" - input: "dense/kernel" - input: "dense/bias" - input: "dense_1/kernel" - input: "dense_1/bias" - input: "total" - input: "count" - input: "total_1" - input: "count_1" - attr { - key: "Tin" - value { - list { - type: DT_STRING - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_STRING - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference__traced_restore_6860" - } - } - } - } - library { - function { - signature { - name: "__inference__traced_restore_6860" - input_arg { - name: "file_prefix" - type: DT_STRING - } - input_arg { - name: "assignvariableop_dense_kernel" - type: DT_RESOURCE - } - input_arg { - name: "assignvariableop_1_dense_bias" - type: DT_RESOURCE - } - input_arg { - name: "assignvariableop_2_dense_1_kernel" - type: DT_RESOURCE - } - input_arg { - name: "assignvariableop_3_dense_1_bias" - type: DT_RESOURCE - } - input_arg { - name: "assignvariableop_4_total" - type: DT_RESOURCE - } - input_arg { - name: "assignvariableop_5_count" - type: DT_RESOURCE - } - input_arg { - name: "assignvariableop_6_total_1" - type: DT_RESOURCE - } - input_arg { - name: "assignvariableop_7_count_1" - type: DT_RESOURCE - } - output_arg { - name: "identity_9" - type: DT_STRING - } - is_stateful: true - control_output: "AssignVariableOp" - control_output: "AssignVariableOp_1" - control_output: "AssignVariableOp_2" - control_output: "AssignVariableOp_3" - control_output: "AssignVariableOp_4" - control_output: "AssignVariableOp_5" - control_output: "AssignVariableOp_6" - control_output: "AssignVariableOp_7" - control_output: "RestoreV2" - control_output: "RestoreV2_1" - } - node_def { - name: "RestoreV2/tensor_names" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 8 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - dim { - size: 8 - } - } - string_val: "layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE" - } - } - } - experimental_debug_info { - original_node_names: "RestoreV2/tensor_names" - } - } - node_def { - name: "RestoreV2/shape_and_slices" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 8 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - dim { - size: 8 - } - } - string_val: "" - string_val: "" - string_val: "" - string_val: "" - string_val: "" - string_val: "" - string_val: "" - string_val: "" - } - } - } - experimental_debug_info { - original_node_names: "RestoreV2/shape_and_slices" - } - } - node_def { - name: "RestoreV2" - op: "RestoreV2" - input: "file_prefix" - input: "RestoreV2/tensor_names:output:0" - input: "RestoreV2/shape_and_slices:output:0" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - attr { - key: "dtypes" - value { - list { - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - } - } - } - experimental_debug_info { - original_node_names: "RestoreV2" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "RestoreV2:tensors:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - node_def { - name: "AssignVariableOp" - op: "AssignVariableOp" - input: "assignvariableop_dense_kernel" - input: "Identity:output:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "AssignVariableOp" - } - } - node_def { - name: "Identity_1" - op: "Identity" - input: "RestoreV2:tensors:1" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_1" - } - } - node_def { - name: "AssignVariableOp_1" - op: "AssignVariableOp" - input: "assignvariableop_1_dense_bias" - input: "Identity_1:output:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "AssignVariableOp_1" - } - } - node_def { - name: "Identity_2" - op: "Identity" - input: "RestoreV2:tensors:2" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_2" - } - } - node_def { - name: "AssignVariableOp_2" - op: "AssignVariableOp" - input: "assignvariableop_2_dense_1_kernel" - input: "Identity_2:output:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "AssignVariableOp_2" - } - } - node_def { - name: "Identity_3" - op: "Identity" - input: "RestoreV2:tensors:3" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_3" - } - } - node_def { - name: "AssignVariableOp_3" - op: "AssignVariableOp" - input: "assignvariableop_3_dense_1_bias" - input: "Identity_3:output:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "AssignVariableOp_3" - } - } - node_def { - name: "Identity_4" - op: "Identity" - input: "RestoreV2:tensors:4" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_4" - } - } - node_def { - name: "AssignVariableOp_4" - op: "AssignVariableOp" - input: "assignvariableop_4_total" - input: "Identity_4:output:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "AssignVariableOp_4" - } - } - node_def { - name: "Identity_5" - op: "Identity" - input: "RestoreV2:tensors:5" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_5" - } - } - node_def { - name: "AssignVariableOp_5" - op: "AssignVariableOp" - input: "assignvariableop_5_count" - input: "Identity_5:output:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "AssignVariableOp_5" - } - } - node_def { - name: "Identity_6" - op: "Identity" - input: "RestoreV2:tensors:6" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_6" - } - } - node_def { - name: "AssignVariableOp_6" - op: "AssignVariableOp" - input: "assignvariableop_6_total_1" - input: "Identity_6:output:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "AssignVariableOp_6" - } - } - node_def { - name: "Identity_7" - op: "Identity" - input: "RestoreV2:tensors:7" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_7" - } - } - node_def { - name: "AssignVariableOp_7" - op: "AssignVariableOp" - input: "assignvariableop_7_count_1" - input: "Identity_7:output:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "AssignVariableOp_7" - } - } - node_def { - name: "RestoreV2_1/tensor_names" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - dim { - size: 1 - } - } - string_val: "_CHECKPOINTABLE_OBJECT_GRAPH" - } - } - } - experimental_debug_info { - original_node_names: "RestoreV2_1/tensor_names" - } - } - node_def { - name: "RestoreV2_1/shape_and_slices" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - dim { - size: 1 - } - } - string_val: "" - } - } - } - experimental_debug_info { - original_node_names: "RestoreV2_1/shape_and_slices" - } - } - node_def { - name: "RestoreV2_1" - op: "RestoreV2" - input: "file_prefix" - input: "RestoreV2_1/tensor_names:output:0" - input: "RestoreV2_1/shape_and_slices:output:0" - input: "^RestoreV2" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - unknown_rank: true - } - } - } - } - attr { - key: "dtypes" - value { - list { - type: DT_STRING - } - } - } - experimental_debug_info { - original_node_names: "RestoreV2_1" - } - } - node_def { - name: "NoOp" - op: "NoOp" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - experimental_debug_info { - original_node_names: "NoOp" - } - } - node_def { - name: "Identity_8" - op: "Identity" - input: "file_prefix" - input: "^AssignVariableOp" - input: "^AssignVariableOp_1" - input: "^AssignVariableOp_2" - input: "^AssignVariableOp_3" - input: "^AssignVariableOp_4" - input: "^AssignVariableOp_5" - input: "^AssignVariableOp_6" - input: "^AssignVariableOp_7" - input: "^NoOp" - device: "/device:CPU:0" - attr { - key: "T" - value { - type: DT_STRING - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_8" - } - } - node_def { - name: "Identity_9" - op: "Identity" - input: "Identity_8:output:0" - input: "^AssignVariableOp" - input: "^AssignVariableOp_1" - input: "^AssignVariableOp_2" - input: "^AssignVariableOp_3" - input: "^AssignVariableOp_4" - input: "^AssignVariableOp_5" - input: "^AssignVariableOp_6" - input: "^AssignVariableOp_7" - input: "^RestoreV2" - input: "^RestoreV2_1" - attr { - key: "T" - value { - type: DT_STRING - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_9" - } - } - ret { - key: "identity_9" - value: "Identity_9:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "AssignVariableOp" - value: "AssignVariableOp" - } - control_ret { - key: "AssignVariableOp_1" - value: "AssignVariableOp_1" - } - control_ret { - key: "AssignVariableOp_2" - value: "AssignVariableOp_2" - } - control_ret { - key: "AssignVariableOp_3" - value: "AssignVariableOp_3" - } - control_ret { - key: "AssignVariableOp_4" - value: "AssignVariableOp_4" - } - control_ret { - key: "AssignVariableOp_5" - value: "AssignVariableOp_5" - } - control_ret { - key: "AssignVariableOp_6" - value: "AssignVariableOp_6" - } - control_ret { - key: "AssignVariableOp_7" - value: "AssignVariableOp_7" - } - control_ret { - key: "RestoreV2" - value: "RestoreV2" - } - control_ret { - key: "RestoreV2_1" - value: "RestoreV2_1" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "file_prefix" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 5 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 6 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 7 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 8 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_fn_6629" - input_arg { - name: "input_1" - type: DT_INT32 - } - input_arg { - name: "unknown" - type: DT_RESOURCE - } - input_arg { - name: "unknown_0" - type: DT_RESOURCE - } - input_arg { - name: "unknown_1" - type: DT_RESOURCE - } - input_arg { - name: "unknown_2" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "StatefulPartitionedCall" - } - node_def { - name: "StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "input_1" - input: "unknown" - input: "unknown_0" - input: "unknown_1" - input: "unknown_2" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - i: 3 - i: 4 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6618" - } - } - } - experimental_debug_info { - original_node_names: "StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "StatefulPartitionedCall:output:0" - input: "^StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "StatefulPartitionedCall" - value: "StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "input_1" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6587" - input_arg { - name: "input_1" - type: DT_INT32 - } - input_arg { - name: "dense_6555" - type: DT_RESOURCE - } - input_arg { - name: "dense_6557" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_6581" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_6583" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "dense/StatefulPartitionedCall" - control_output: "dense_1/StatefulPartitionedCall" - } - node_def { - name: "dense/StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "input_1" - input: "dense_6555" - input: "dense_6557" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_layer_call_and_return_conditional_losses_6544" - } - } - } - experimental_debug_info { - original_node_names: "dense/StatefulPartitionedCall" - } - } - node_def { - name: "dense_1/StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "dense/StatefulPartitionedCall:output:0" - input: "dense_1_6581" - input: "dense_1_6583" - attr { - key: "Tin" - value { - list { - type: DT_FLOAT - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" - } - } - } - experimental_debug_info { - original_node_names: "dense_1/StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "dense_1/StatefulPartitionedCall:output:0" - input: "^dense/StatefulPartitionedCall" - input: "^dense_1/StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "dense/StatefulPartitionedCall" - value: "dense/StatefulPartitionedCall" - } - control_ret { - key: "dense_1/StatefulPartitionedCall" - value: "dense_1/StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "input_1" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6618" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "dense_6607" - type: DT_RESOURCE - } - input_arg { - name: "dense_6609" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_6612" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_6614" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "dense/StatefulPartitionedCall" - control_output: "dense_1/StatefulPartitionedCall" - } - node_def { - name: "dense/StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "inputs" - input: "dense_6607" - input: "dense_6609" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_layer_call_and_return_conditional_losses_6544" - } - } - } - experimental_debug_info { - original_node_names: "dense/StatefulPartitionedCall" - } - } - node_def { - name: "dense_1/StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "dense/StatefulPartitionedCall:output:0" - input: "dense_1_6612" - input: "dense_1_6614" - attr { - key: "Tin" - value { - list { - type: DT_FLOAT - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" - } - } - } - experimental_debug_info { - original_node_names: "dense_1/StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "dense_1/StatefulPartitionedCall:output:0" - input: "^dense/StatefulPartitionedCall" - input: "^dense_1/StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "dense/StatefulPartitionedCall" - value: "dense/StatefulPartitionedCall" - } - control_ret { - key: "dense_1/StatefulPartitionedCall" - value: "dense_1/StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_fn_6656" - input_arg { - name: "input_1" - type: DT_INT32 - } - input_arg { - name: "unknown" - type: DT_RESOURCE - } - input_arg { - name: "unknown_0" - type: DT_RESOURCE - } - input_arg { - name: "unknown_1" - type: DT_RESOURCE - } - input_arg { - name: "unknown_2" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "StatefulPartitionedCall" - } - node_def { - name: "StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "input_1" - input: "unknown" - input: "unknown_0" - input: "unknown_1" - input: "unknown_2" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - i: 3 - i: 4 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6645" - } - } - } - experimental_debug_info { - original_node_names: "StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "StatefulPartitionedCall:output:0" - input: "^StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "StatefulPartitionedCall" - value: "StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "input_1" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_dense_1_layer_call_and_return_conditional_losses_6764" - input_arg { - name: "inputs" - type: DT_FLOAT - } - input_arg { - name: "matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "biasadd_readvariableop_resource" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - } - node_def { - name: "MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "MatMul/ReadVariableOp" - } - } - node_def { - name: "MatMul" - op: "MatMul" - input: "inputs" - input: "MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "MatMul" - } - } - node_def { - name: "BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "BiasAdd/ReadVariableOp" - } - } - node_def { - name: "BiasAdd" - op: "BiasAdd" - input: "MatMul:product:0" - input: "BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "BiasAdd" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_dense_layer_call_fn_6754" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "unknown" - type: DT_RESOURCE - } - input_arg { - name: "unknown_0" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "StatefulPartitionedCall" - } - node_def { - name: "StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "inputs" - input: "unknown" - input: "unknown_0" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_layer_call_and_return_conditional_losses_6544" - } - } - } - experimental_debug_info { - original_node_names: "StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "StatefulPartitionedCall:output:0" - input: "^StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "StatefulPartitionedCall" - value: "StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference__traced_save_6824" - input_arg { - name: "file_prefix" - type: DT_STRING - } - input_arg { - name: "savev2_dense_kernel_read_readvariableop" - type: DT_FLOAT - } - input_arg { - name: "savev2_dense_bias_read_readvariableop" - type: DT_FLOAT - } - input_arg { - name: "savev2_dense_1_kernel_read_readvariableop" - type: DT_FLOAT - } - input_arg { - name: "savev2_dense_1_bias_read_readvariableop" - type: DT_FLOAT - } - input_arg { - name: "savev2_total_read_readvariableop" - type: DT_FLOAT - } - input_arg { - name: "savev2_count_read_readvariableop" - type: DT_FLOAT - } - input_arg { - name: "savev2_total_1_read_readvariableop" - type: DT_FLOAT - } - input_arg { - name: "savev2_count_1_read_readvariableop" - type: DT_FLOAT - } - input_arg { - name: "savev2_1_const" - type: DT_STRING - } - output_arg { - name: "identity_1" - type: DT_STRING - } - is_stateful: true - control_output: "MergeV2Checkpoints" - control_output: "SaveV2" - control_output: "SaveV2_1" - } - node_def { - name: "StaticRegexFullMatch" - op: "StaticRegexFullMatch" - input: "file_prefix" - device: "/device:CPU:*" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "pattern" - value { - s: "^s3://.*" - } - } - experimental_debug_info { - original_node_names: "StaticRegexFullMatch" - } - } - node_def { - name: "Const" - op: "Const" - device: "/device:CPU:*" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - } - string_val: ".part" - } - } - } - experimental_debug_info { - original_node_names: "Const" - } - } - node_def { - name: "Const_1" - op: "Const" - device: "/device:CPU:*" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - } - string_val: "_temp_6f1e5fef49bb4c06ace07a8a95dfbb1b/part" - } - } - } - experimental_debug_info { - original_node_names: "Const_1" - } - } - node_def { - name: "Select" - op: "Select" - input: "StaticRegexFullMatch:output:0" - input: "Const:output:0" - input: "Const_1:output:0" - device: "/device:CPU:*" - attr { - key: "T" - value { - type: DT_STRING - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - experimental_debug_info { - original_node_names: "Select" - } - } - node_def { - name: "StringJoin" - op: "StringJoin" - input: "file_prefix" - input: "Select:output:0" - device: "/device:CPU:*" - attr { - key: "N" - value { - i: 2 - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - experimental_debug_info { - original_node_names: "StringJoin" - } - } - node_def { - name: "num_shards" - op: "Const" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_INT32 - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_INT32 - tensor_shape { - } - int_val: 2 - } - } - } - experimental_debug_info { - original_node_names: "num_shards" - } - } - node_def { - name: "ShardedFilename/shard" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_INT32 - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_INT32 - tensor_shape { - } - int_val: 0 - } - } - } - experimental_debug_info { - original_node_names: "ShardedFilename/shard" - } - } - node_def { - name: "ShardedFilename" - op: "ShardedFilename" - input: "StringJoin:output:0" - input: "ShardedFilename/shard:output:0" - input: "num_shards:output:0" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - experimental_debug_info { - original_node_names: "ShardedFilename" - } - } - node_def { - name: "SaveV2/tensor_names" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 8 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - dim { - size: 8 - } - } - string_val: "layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE" - string_val: "keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE" - } - } - } - experimental_debug_info { - original_node_names: "SaveV2/tensor_names" - } - } - node_def { - name: "SaveV2/shape_and_slices" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 8 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - dim { - size: 8 - } - } - string_val: "" - string_val: "" - string_val: "" - string_val: "" - string_val: "" - string_val: "" - string_val: "" - string_val: "" - } - } - } - experimental_debug_info { - original_node_names: "SaveV2/shape_and_slices" - } - } - node_def { - name: "SaveV2" - op: "SaveV2" - input: "ShardedFilename:filename:0" - input: "SaveV2/tensor_names:output:0" - input: "SaveV2/shape_and_slices:output:0" - input: "savev2_dense_kernel_read_readvariableop" - input: "savev2_dense_bias_read_readvariableop" - input: "savev2_dense_1_kernel_read_readvariableop" - input: "savev2_dense_1_bias_read_readvariableop" - input: "savev2_total_read_readvariableop" - input: "savev2_count_read_readvariableop" - input: "savev2_total_1_read_readvariableop" - input: "savev2_count_1_read_readvariableop" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtypes" - value { - list { - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - type: DT_FLOAT - } - } - } - experimental_debug_info { - original_node_names: "SaveV2" - } - } - node_def { - name: "ShardedFilename_1/shard" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "dtype" - value { - type: DT_INT32 - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_INT32 - tensor_shape { - } - int_val: 1 - } - } - } - experimental_debug_info { - original_node_names: "ShardedFilename_1/shard" - } - } - node_def { - name: "ShardedFilename_1" - op: "ShardedFilename" - input: "StringJoin:output:0" - input: "ShardedFilename_1/shard:output:0" - input: "num_shards:output:0" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - experimental_debug_info { - original_node_names: "ShardedFilename_1" - } - } - node_def { - name: "SaveV2_1/tensor_names" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - dim { - size: 1 - } - } - string_val: "_CHECKPOINTABLE_OBJECT_GRAPH" - } - } - } - experimental_debug_info { - original_node_names: "SaveV2_1/tensor_names" - } - } - node_def { - name: "SaveV2_1/shape_and_slices" - op: "Const" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_STRING - } - } - attr { - key: "value" - value { - tensor { - dtype: DT_STRING - tensor_shape { - dim { - size: 1 - } - } - string_val: "" - } - } - } - experimental_debug_info { - original_node_names: "SaveV2_1/shape_and_slices" - } - } - node_def { - name: "SaveV2_1" - op: "SaveV2" - input: "ShardedFilename_1:filename:0" - input: "SaveV2_1/tensor_names:output:0" - input: "SaveV2_1/shape_and_slices:output:0" - input: "savev2_1_const" - input: "^SaveV2" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - attr { - key: "dtypes" - value { - list { - type: DT_STRING - } - } - } - experimental_debug_info { - original_node_names: "SaveV2_1" - } - } - node_def { - name: "MergeV2Checkpoints/checkpoint_prefixes" - op: "Pack" - input: "ShardedFilename:filename:0" - input: "ShardedFilename_1:filename:0" - input: "^SaveV2" - input: "^SaveV2_1" - device: "/device:CPU:0" - attr { - key: "N" - value { - i: 2 - } - } - attr { - key: "T" - value { - type: DT_STRING - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 2 - } - } - } - } - } - experimental_debug_info { - original_node_names: "MergeV2Checkpoints/checkpoint_prefixes" - } - } - node_def { - name: "MergeV2Checkpoints" - op: "MergeV2Checkpoints" - input: "MergeV2Checkpoints/checkpoint_prefixes:output:0" - input: "file_prefix" - input: "^SaveV2_1" - device: "/device:CPU:0" - attr { - key: "_output_shapes" - value { - list { - } - } - } - experimental_debug_info { - original_node_names: "MergeV2Checkpoints" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "file_prefix" - input: "^MergeV2Checkpoints" - device: "/device:CPU:0" - attr { - key: "T" - value { - type: DT_STRING - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - node_def { - name: "Identity_1" - op: "Identity" - input: "Identity:output:0" - input: "^MergeV2Checkpoints" - input: "^SaveV2" - input: "^SaveV2_1" - attr { - key: "T" - value { - type: DT_STRING - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - experimental_debug_info { - original_node_names: "Identity_1" - } - } - ret { - key: "identity_1" - value: "Identity_1:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - } - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - shape { - dim { - size: 100 - } - } - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - shape { - dim { - size: 1 - } - } - shape { - } - shape { - } - shape { - } - shape { - } - shape { - } - } - } - } - control_ret { - key: "MergeV2Checkpoints" - value: "MergeV2Checkpoints" - } - control_ret { - key: "SaveV2" - value: "SaveV2" - } - control_ret { - key: "SaveV2_1" - value: "SaveV2_1" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "file_prefix" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - } - } - arg_attr { - key: 5 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 6 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 7 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 8 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 9 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6689" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "dense_matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "dense_biasadd_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_biasadd_readvariableop_resource" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - } - node_def { - name: "dense/Cast" - op: "Cast" - input: "inputs" - attr { - key: "DstT" - value { - type: DT_FLOAT - } - } - attr { - key: "SrcT" - value { - type: DT_INT32 - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense/Cast" - } - } - node_def { - name: "dense/MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "dense/MatMul/ReadVariableOp" - } - } - node_def { - name: "dense/MatMul" - op: "MatMul" - input: "dense/Cast:y:0" - input: "dense/MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense/MatMul" - } - } - node_def { - name: "dense/BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "dense/BiasAdd/ReadVariableOp" - } - } - node_def { - name: "dense/BiasAdd" - op: "BiasAdd" - input: "dense/MatMul:product:0" - input: "dense/BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense/BiasAdd" - } - } - node_def { - name: "dense/Relu" - op: "Relu" - input: "dense/BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense/Relu" - } - } - node_def { - name: "dense_1/MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_1_matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "dense_1/MatMul/ReadVariableOp" - } - } - node_def { - name: "dense_1/MatMul" - op: "MatMul" - input: "dense/Relu:activations:0" - input: "dense_1/MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense_1/MatMul" - } - } - node_def { - name: "dense_1/BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_1_biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "dense_1/BiasAdd/ReadVariableOp" - } - } - node_def { - name: "dense_1/BiasAdd" - op: "BiasAdd" - input: "dense_1/MatMul:product:0" - input: "dense_1/BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense_1/BiasAdd" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "dense_1/BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_dense_layer_call_and_return_conditional_losses_6745" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "biasadd_readvariableop_resource" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - } - node_def { - name: "Cast" - op: "Cast" - input: "inputs" - attr { - key: "DstT" - value { - type: DT_FLOAT - } - } - attr { - key: "SrcT" - value { - type: DT_INT32 - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Cast" - } - } - node_def { - name: "MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "MatMul/ReadVariableOp" - } - } - node_def { - name: "MatMul" - op: "MatMul" - input: "Cast:y:0" - input: "MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "MatMul" - } - } - node_def { - name: "BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "BiasAdd/ReadVariableOp" - } - } - node_def { - name: "BiasAdd" - op: "BiasAdd" - input: "MatMul:product:0" - input: "BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "BiasAdd" - } - } - node_def { - name: "Relu" - op: "Relu" - input: "BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Relu" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "Relu:activations:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_dense_1_layer_call_fn_6773" - input_arg { - name: "inputs" - type: DT_FLOAT - } - input_arg { - name: "unknown" - type: DT_RESOURCE - } - input_arg { - name: "unknown_0" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "StatefulPartitionedCall" - } - node_def { - name: "StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "inputs" - input: "unknown" - input: "unknown_0" - attr { - key: "Tin" - value { - list { - type: DT_FLOAT - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" - } - } - } - experimental_debug_info { - original_node_names: "StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "StatefulPartitionedCall:output:0" - input: "^StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "StatefulPartitionedCall" - value: "StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference__wrapped_model_6528" - input_arg { - name: "input_1" - type: DT_INT32 - } - input_arg { - name: "sequential_dense_matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "sequential_dense_biasadd_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "sequential_dense_1_matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "sequential_dense_1_biasadd_readvariableop_resource" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - } - node_def { - name: "sequential/dense/Cast" - op: "Cast" - input: "input_1" - attr { - key: "DstT" - value { - type: DT_FLOAT - } - } - attr { - key: "SrcT" - value { - type: DT_INT32 - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - experimental_debug_info { - original_node_names: "sequential/dense/Cast" - } - } - node_def { - name: "sequential/dense/MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "sequential_dense_matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "sequential/dense/MatMul/ReadVariableOp" - } - } - node_def { - name: "sequential/dense/MatMul" - op: "MatMul" - input: "sequential/dense/Cast:y:0" - input: "sequential/dense/MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "sequential/dense/MatMul" - } - } - node_def { - name: "sequential/dense/BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "sequential_dense_biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "sequential/dense/BiasAdd/ReadVariableOp" - } - } - node_def { - name: "sequential/dense/BiasAdd" - op: "BiasAdd" - input: "sequential/dense/MatMul:product:0" - input: "sequential/dense/BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "sequential/dense/BiasAdd" - } - } - node_def { - name: "sequential/dense/Relu" - op: "Relu" - input: "sequential/dense/BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "sequential/dense/Relu" - } - } - node_def { - name: "sequential/dense_1/MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "sequential_dense_1_matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "sequential/dense_1/MatMul/ReadVariableOp" - } - } - node_def { - name: "sequential/dense_1/MatMul" - op: "MatMul" - input: "sequential/dense/Relu:activations:0" - input: "sequential/dense_1/MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "sequential/dense_1/MatMul" - } - } - node_def { - name: "sequential/dense_1/BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "sequential_dense_1_biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "sequential/dense_1/BiasAdd/ReadVariableOp" - } - } - node_def { - name: "sequential/dense_1/BiasAdd" - op: "BiasAdd" - input: "sequential/dense_1/MatMul:product:0" - input: "sequential/dense_1/BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "sequential/dense_1/BiasAdd" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "sequential/dense_1/BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "input_1" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_dense_layer_call_and_return_conditional_losses_6544" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "biasadd_readvariableop_resource" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - } - node_def { - name: "Cast" - op: "Cast" - input: "inputs" - attr { - key: "DstT" - value { - type: DT_FLOAT - } - } - attr { - key: "SrcT" - value { - type: DT_INT32 - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Cast" - } - } - node_def { - name: "MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "MatMul/ReadVariableOp" - } - } - node_def { - name: "MatMul" - op: "MatMul" - input: "Cast:y:0" - input: "MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "MatMul" - } - } - node_def { - name: "BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "BiasAdd/ReadVariableOp" - } - } - node_def { - name: "BiasAdd" - op: "BiasAdd" - input: "MatMul:product:0" - input: "BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "BiasAdd" - } - } - node_def { - name: "Relu" - op: "Relu" - input: "BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Relu" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "Relu:activations:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6601" - input_arg { - name: "input_1" - type: DT_INT32 - } - input_arg { - name: "dense_6590" - type: DT_RESOURCE - } - input_arg { - name: "dense_6592" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_6595" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_6597" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "dense/StatefulPartitionedCall" - control_output: "dense_1/StatefulPartitionedCall" - } - node_def { - name: "dense/StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "input_1" - input: "dense_6590" - input: "dense_6592" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_layer_call_and_return_conditional_losses_6544" - } - } - } - experimental_debug_info { - original_node_names: "dense/StatefulPartitionedCall" - } - } - node_def { - name: "dense_1/StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "dense/StatefulPartitionedCall:output:0" - input: "dense_1_6595" - input: "dense_1_6597" - attr { - key: "Tin" - value { - list { - type: DT_FLOAT - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" - } - } - } - experimental_debug_info { - original_node_names: "dense_1/StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "dense_1/StatefulPartitionedCall:output:0" - input: "^dense/StatefulPartitionedCall" - input: "^dense_1/StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "dense/StatefulPartitionedCall" - value: "dense/StatefulPartitionedCall" - } - control_ret { - key: "dense_1/StatefulPartitionedCall" - value: "dense_1/StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "input_1" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_fn_6733" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "unknown" - type: DT_RESOURCE - } - input_arg { - name: "unknown_0" - type: DT_RESOURCE - } - input_arg { - name: "unknown_1" - type: DT_RESOURCE - } - input_arg { - name: "unknown_2" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "StatefulPartitionedCall" - } - node_def { - name: "StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "inputs" - input: "unknown" - input: "unknown_0" - input: "unknown_1" - input: "unknown_2" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - i: 3 - i: 4 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6645" - } - } - } - experimental_debug_info { - original_node_names: "StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "StatefulPartitionedCall:output:0" - input: "^StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "StatefulPartitionedCall" - value: "StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6645" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "dense_6634" - type: DT_RESOURCE - } - input_arg { - name: "dense_6636" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_6639" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_6641" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "dense/StatefulPartitionedCall" - control_output: "dense_1/StatefulPartitionedCall" - } - node_def { - name: "dense/StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "inputs" - input: "dense_6634" - input: "dense_6636" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_layer_call_and_return_conditional_losses_6544" - } - } - } - experimental_debug_info { - original_node_names: "dense/StatefulPartitionedCall" - } - } - node_def { - name: "dense_1/StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "dense/StatefulPartitionedCall:output:0" - input: "dense_1_6639" - input: "dense_1_6641" - attr { - key: "Tin" - value { - list { - type: DT_FLOAT - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" - } - } - } - experimental_debug_info { - original_node_names: "dense_1/StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "dense_1/StatefulPartitionedCall:output:0" - input: "^dense/StatefulPartitionedCall" - input: "^dense_1/StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "dense/StatefulPartitionedCall" - value: "dense/StatefulPartitionedCall" - } - control_ret { - key: "dense_1/StatefulPartitionedCall" - value: "dense_1/StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" - input_arg { - name: "inputs" - type: DT_FLOAT - } - input_arg { - name: "matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "biasadd_readvariableop_resource" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - } - node_def { - name: "MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "MatMul/ReadVariableOp" - } - } - node_def { - name: "MatMul" - op: "MatMul" - input: "inputs" - input: "MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "MatMul" - } - } - node_def { - name: "BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "BiasAdd/ReadVariableOp" - } - } - node_def { - name: "BiasAdd" - op: "BiasAdd" - input: "MatMul:product:0" - input: "BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "BiasAdd" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_signature_wrapper_6671" - input_arg { - name: "input_1" - type: DT_INT32 - } - input_arg { - name: "unknown" - type: DT_RESOURCE - } - input_arg { - name: "unknown_0" - type: DT_RESOURCE - } - input_arg { - name: "unknown_1" - type: DT_RESOURCE - } - input_arg { - name: "unknown_2" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "StatefulPartitionedCall" - } - node_def { - name: "StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "input_1" - input: "unknown" - input: "unknown_0" - input: "unknown_1" - input: "unknown_2" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - i: 3 - i: 4 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference__wrapped_model_6528" - } - } - } - experimental_debug_info { - original_node_names: "StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "StatefulPartitionedCall:output:0" - input: "^StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "StatefulPartitionedCall" - value: "StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "input_1" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_fn_6720" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "unknown" - type: DT_RESOURCE - } - input_arg { - name: "unknown_0" - type: DT_RESOURCE - } - input_arg { - name: "unknown_1" - type: DT_RESOURCE - } - input_arg { - name: "unknown_2" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - control_output: "StatefulPartitionedCall" - } - node_def { - name: "StatefulPartitionedCall" - op: "StatefulPartitionedCall" - input: "inputs" - input: "unknown" - input: "unknown_0" - input: "unknown_1" - input: "unknown_2" - attr { - key: "Tin" - value { - list { - type: DT_INT32 - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - type: DT_RESOURCE - } - } - } - attr { - key: "Tout" - value { - list { - type: DT_FLOAT - } - } - } - attr { - key: "_collective_manager_ids" - value { - list { - } - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "_read_only_resource_inputs" - value { - list { - i: 1 - i: 2 - i: 3 - i: 4 - } - } - } - attr { - key: "config_proto" - value { - s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" - } - } - attr { - key: "f" - value { - func { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6618" - } - } - } - experimental_debug_info { - original_node_names: "StatefulPartitionedCall" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "StatefulPartitionedCall:output:0" - input: "^StatefulPartitionedCall" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - control_ret { - key: "StatefulPartitionedCall" - value: "StatefulPartitionedCall" - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - function { - signature { - name: "__inference_sequential_layer_call_and_return_conditional_losses_6707" - input_arg { - name: "inputs" - type: DT_INT32 - } - input_arg { - name: "dense_matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "dense_biasadd_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_matmul_readvariableop_resource" - type: DT_RESOURCE - } - input_arg { - name: "dense_1_biasadd_readvariableop_resource" - type: DT_RESOURCE - } - output_arg { - name: "identity" - type: DT_FLOAT - } - is_stateful: true - } - node_def { - name: "dense/Cast" - op: "Cast" - input: "inputs" - attr { - key: "DstT" - value { - type: DT_FLOAT - } - } - attr { - key: "SrcT" - value { - type: DT_INT32 - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense/Cast" - } - } - node_def { - name: "dense/MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "dense/MatMul/ReadVariableOp" - } - } - node_def { - name: "dense/MatMul" - op: "MatMul" - input: "dense/Cast:y:0" - input: "dense/MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense/MatMul" - } - } - node_def { - name: "dense/BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "dense/BiasAdd/ReadVariableOp" - } - } - node_def { - name: "dense/BiasAdd" - op: "BiasAdd" - input: "dense/MatMul:product:0" - input: "dense/BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense/BiasAdd" - } - } - node_def { - name: "dense/Relu" - op: "Relu" - input: "dense/BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense/Relu" - } - } - node_def { - name: "dense_1/MatMul/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_1_matmul_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "dense_1/MatMul/ReadVariableOp" - } - } - node_def { - name: "dense_1/MatMul" - op: "MatMul" - input: "dense/Relu:activations:0" - input: "dense_1/MatMul/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense_1/MatMul" - } - } - node_def { - name: "dense_1/BiasAdd/ReadVariableOp" - op: "ReadVariableOp" - input: "dense_1_biasadd_readvariableop_resource" - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: 1 - } - } - } - } - } - attr { - key: "dtype" - value { - type: DT_FLOAT - } - } - experimental_debug_info { - original_node_names: "dense_1/BiasAdd/ReadVariableOp" - } - } - node_def { - name: "dense_1/BiasAdd" - op: "BiasAdd" - input: "dense_1/MatMul:product:0" - input: "dense_1/BiasAdd/ReadVariableOp:value:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "dense_1/BiasAdd" - } - } - node_def { - name: "Identity" - op: "Identity" - input: "dense_1/BiasAdd:output:0" - attr { - key: "T" - value { - type: DT_FLOAT - } - } - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - } - experimental_debug_info { - original_node_names: "Identity" - } - } - ret { - key: "identity" - value: "Identity:output:0" - } - attr { - key: "_input_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - shape { - unknown_rank: true - } - } - } - } - arg_attr { - key: 0 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - } - attr { - key: "_user_specified_name" - value { - s: "inputs" - } - } - } - } - arg_attr { - key: 1 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 2 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 3 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - arg_attr { - key: 4 - value { - attr { - key: "_output_shapes" - value { - list { - shape { - } - } - } - } - } - } - } - } - versions { - producer: 331 - min_consumer: 12 - } - } - saver_def { - filename_tensor_name: "saver_filename:0" - save_tensor_name: "StatefulPartitionedCall_1:0" - restore_op_name: "StatefulPartitionedCall_2" - version: V2 - } - collection_def { - key: "saved_model_main_op" - value { - node_list { - value: "NoOp" - } - } - } - signature_def { - key: "__saved_model_init_op" - value { - outputs { - key: "__saved_model_init_op" - value { - name: "NoOp" - tensor_shape { - unknown_rank: true - } - } - } - } - } - signature_def { - key: "serving_default" - value { - inputs { - key: "input_1" - value { - name: "serving_default_input_1:0" - dtype: DT_INT32 - tensor_shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - } - } - outputs { - key: "output_1" - value { - name: "StatefulPartitionedCall:0" - dtype: DT_FLOAT - tensor_shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - } - } - method_name: "tensorflow/serving/predict" - } - } - object_graph_def { - nodes { - children { - node_id: 1 - local_name: "layer_with_weights-0" - } - children { - node_id: 1 - local_name: "layer-0" - } - children { - node_id: 2 - local_name: "layer_with_weights-1" - } - children { - node_id: 2 - local_name: "layer-1" - } - children { - node_id: 3 - local_name: "optimizer" - } - children { - node_id: 4 - local_name: "regularization_losses" - } - children { - node_id: 5 - local_name: "variables" - } - children { - node_id: 6 - local_name: "trainable_variables" - } - children { - node_id: 7 - local_name: "keras_api" - } - children { - node_id: 8 - local_name: "signatures" - } - children { - node_id: 47 - local_name: "__call__" - } - children { - node_id: 48 - local_name: "_default_save_signature" - } - children { - node_id: 49 - local_name: "call_and_return_all_conditional_losses" - } - user_object { - identifier: "_tf_keras_sequential" - version { - producer: 1 - min_consumer: 1 - } - metadata: "{\"class_name\": \"Sequential\", \"name\": \"sequential\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"config\": {\"name\": \"sequential\", \"layers\": [{\"class_name\": \"Dense\", \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}, {\"class_name\": \"Dense\", \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}], \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 214}}}, \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}, \"is_graph_network\": false, \"keras_version\": \"2.2.4-tf\", \"backend\": \"tensorflow\", \"model_config\": {\"class_name\": \"Sequential\", \"config\": {\"name\": \"sequential\", \"layers\": [{\"class_name\": \"Dense\", \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}, {\"class_name\": \"Dense\", \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}], \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}}}, \"training_config\": {\"loss\": \"mean_absolute_error\", \"metrics\": [\"mean_squared_error\"], \"weighted_metrics\": null, \"loss_weights\": null, \"sample_weight_mode\": null, \"optimizer_config\": {\"class_name\": \"Adam\", \"config\": {\"name\": \"Adam\", \"learning_rate\": 0.0003000000142492354, \"decay\": 0.0, \"beta_1\": 0.8999999761581421, \"beta_2\": 0.9990000128746033, \"epsilon\": 1e-07, \"amsgrad\": false}}}}" - } - } - nodes { - children { - node_id: 9 - local_name: "kernel" - } - children { - node_id: 10 - local_name: "bias" - } - children { - node_id: 11 - local_name: "regularization_losses" - } - children { - node_id: 12 - local_name: "variables" - } - children { - node_id: 13 - local_name: "trainable_variables" - } - children { - node_id: 14 - local_name: "keras_api" - } - children { - node_id: 50 - local_name: "__call__" - } - children { - node_id: 51 - local_name: "call_and_return_all_conditional_losses" - } - user_object { - identifier: "_tf_keras_layer" - version { - producer: 1 - min_consumer: 1 - } - metadata: "{\"class_name\": \"Dense\", \"name\": \"dense\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 214}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [null, 214]}}" - } - } - nodes { - children { - node_id: 15 - local_name: "kernel" - } - children { - node_id: 16 - local_name: "bias" - } - children { - node_id: 17 - local_name: "regularization_losses" - } - children { - node_id: 18 - local_name: "variables" - } - children { - node_id: 19 - local_name: "trainable_variables" - } - children { - node_id: 20 - local_name: "keras_api" - } - children { - node_id: 52 - local_name: "__call__" - } - children { - node_id: 53 - local_name: "call_and_return_all_conditional_losses" - } - user_object { - identifier: "_tf_keras_layer" - version { - producer: 1 - min_consumer: 1 - } - metadata: "{\"class_name\": \"Dense\", \"name\": \"dense_1\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 100}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [null, 100]}}" - } - } - nodes { - user_object { - identifier: "optimizer" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 9 - local_name: "0" - } - children { - node_id: 10 - local_name: "1" - } - children { - node_id: 15 - local_name: "2" - } - children { - node_id: 16 - local_name: "3" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 9 - local_name: "0" - } - children { - node_id: 10 - local_name: "1" - } - children { - node_id: 15 - local_name: "2" - } - children { - node_id: 16 - local_name: "3" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 21 - local_name: "layers" - } - children { - node_id: 22 - local_name: "layer_regularization_losses" - } - children { - node_id: 23 - local_name: "non_trainable_variables" - } - children { - node_id: 24 - local_name: "layer_metrics" - } - children { - node_id: 4 - local_name: "regularization_losses" - } - children { - node_id: 25 - local_name: "metrics" - } - children { - node_id: 5 - local_name: "variables" - } - children { - node_id: 6 - local_name: "trainable_variables" - } - children { - node_id: 47 - local_name: "__call__" - } - children { - node_id: 48 - local_name: "_default_save_signature" - } - children { - node_id: 49 - local_name: "call_and_return_all_conditional_losses" - } - children { - node_id: 49 - local_name: "call_and_return_conditional_losses" - } - user_object { - identifier: "_generic_user_object" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 54 - local_name: "serving_default" - } - user_object { - identifier: "signature_map" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - variable { - dtype: DT_FLOAT - shape { - dim { - size: 214 - } - dim { - size: 100 - } - } - trainable: true - name: "dense/kernel" - } - } - nodes { - variable { - dtype: DT_FLOAT - shape { - dim { - size: 100 - } - } - trainable: true - name: "dense/bias" - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 9 - local_name: "0" - } - children { - node_id: 10 - local_name: "1" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 9 - local_name: "0" - } - children { - node_id: 10 - local_name: "1" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 26 - local_name: "layers" - } - children { - node_id: 27 - local_name: "layer_regularization_losses" - } - children { - node_id: 28 - local_name: "non_trainable_variables" - } - children { - node_id: 29 - local_name: "layer_metrics" - } - children { - node_id: 11 - local_name: "regularization_losses" - } - children { - node_id: 30 - local_name: "metrics" - } - children { - node_id: 12 - local_name: "variables" - } - children { - node_id: 13 - local_name: "trainable_variables" - } - children { - node_id: 50 - local_name: "__call__" - } - children { - node_id: 51 - local_name: "call_and_return_all_conditional_losses" - } - children { - node_id: 51 - local_name: "call_and_return_conditional_losses" - } - user_object { - identifier: "_generic_user_object" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - variable { - dtype: DT_FLOAT - shape { - dim { - size: 100 - } - dim { - size: 1 - } - } - trainable: true - name: "dense_1/kernel" - } - } - nodes { - variable { - dtype: DT_FLOAT - shape { - dim { - size: 1 - } - } - trainable: true - name: "dense_1/bias" - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 15 - local_name: "0" - } - children { - node_id: 16 - local_name: "1" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 15 - local_name: "0" - } - children { - node_id: 16 - local_name: "1" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 31 - local_name: "layers" - } - children { - node_id: 32 - local_name: "layer_regularization_losses" - } - children { - node_id: 33 - local_name: "non_trainable_variables" - } - children { - node_id: 34 - local_name: "layer_metrics" - } - children { - node_id: 17 - local_name: "regularization_losses" - } - children { - node_id: 35 - local_name: "metrics" - } - children { - node_id: 18 - local_name: "variables" - } - children { - node_id: 19 - local_name: "trainable_variables" - } - children { - node_id: 52 - local_name: "__call__" - } - children { - node_id: 53 - local_name: "call_and_return_all_conditional_losses" - } - children { - node_id: 53 - local_name: "call_and_return_conditional_losses" - } - user_object { - identifier: "_generic_user_object" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 1 - local_name: "0" - } - children { - node_id: 2 - local_name: "1" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_dict_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 36 - local_name: "0" - } - children { - node_id: 37 - local_name: "1" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_dict_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_dict_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 38 - local_name: "total" - } - children { - node_id: 39 - local_name: "count" - } - children { - node_id: 40 - local_name: "variables" - } - children { - node_id: 41 - local_name: "keras_api" - } - user_object { - identifier: "_tf_keras_metric" - version { - producer: 1 - min_consumer: 1 - } - metadata: "{\"class_name\": \"Mean\", \"name\": \"loss\", \"dtype\": \"float32\", \"config\": {\"name\": \"loss\", \"dtype\": \"float32\"}}" - } - } - nodes { - children { - node_id: 42 - local_name: "total" - } - children { - node_id: 43 - local_name: "count" - } - children { - node_id: 44 - local_name: "_fn_kwargs" - } - children { - node_id: 45 - local_name: "variables" - } - children { - node_id: 46 - local_name: "keras_api" - } - user_object { - identifier: "_tf_keras_metric" - version { - producer: 1 - min_consumer: 1 - } - metadata: "{\"class_name\": \"MeanMetricWrapper\", \"name\": \"mean_squared_error\", \"dtype\": \"float32\", \"config\": {\"name\": \"mean_squared_error\", \"dtype\": \"float32\", \"fn\": \"mean_squared_error\"}}" - } - } - nodes { - variable { - dtype: DT_FLOAT - shape { - } - synchronization: VARIABLE_SYNCHRONIZATION_ON_READ - aggregation: VARIABLE_AGGREGATION_SUM - name: "total" - } - } - nodes { - variable { - dtype: DT_FLOAT - shape { - } - synchronization: VARIABLE_SYNCHRONIZATION_ON_READ - aggregation: VARIABLE_AGGREGATION_SUM - name: "count" - } - } - nodes { - children { - node_id: 38 - local_name: "0" - } - children { - node_id: 39 - local_name: "1" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 40 - local_name: "variables" - } - user_object { - identifier: "_generic_user_object" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - variable { - dtype: DT_FLOAT - shape { - } - synchronization: VARIABLE_SYNCHRONIZATION_ON_READ - aggregation: VARIABLE_AGGREGATION_SUM - name: "total" - } - } - nodes { - variable { - dtype: DT_FLOAT - shape { - } - synchronization: VARIABLE_SYNCHRONIZATION_ON_READ - aggregation: VARIABLE_AGGREGATION_SUM - name: "count" - } - } - nodes { - user_object { - identifier: "trackable_dict_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 42 - local_name: "0" - } - children { - node_id: 43 - local_name: "1" - } - user_object { - identifier: "trackable_list_wrapper" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - children { - node_id: 45 - local_name: "variables" - } - user_object { - identifier: "_generic_user_object" - version { - producer: 1 - min_consumer: 1 - } - } - } - nodes { - function { - concrete_functions: "__inference_sequential_layer_call_fn_6629" - concrete_functions: "__inference_sequential_layer_call_fn_6733" - concrete_functions: "__inference_sequential_layer_call_fn_6720" - concrete_functions: "__inference_sequential_layer_call_fn_6656" - function_spec { - fullargspec { - named_tuple_value { - name: "FullArgSpec" - values { - key: "args" - value { - list_value { - values { - string_value: "self" - } - values { - string_value: "inputs" - } - values { - string_value: "training" - } - values { - string_value: "mask" - } - } - } - } - values { - key: "varargs" - value { - none_value { - } - } - } - values { - key: "varkw" - value { - none_value { - } - } - } - values { - key: "defaults" - value { - list_value { - values { - bool_value: false - } - values { - none_value { - } - } - } - } - } - values { - key: "kwonlyargs" - value { - list_value { - } - } - } - values { - key: "kwonlydefaults" - value { - dict_value { - } - } - } - values { - key: "annotations" - value { - dict_value { - } - } - } - } - } - is_method: true - input_signature { - none_value { - } - } - } - } - } - nodes { - function { - concrete_functions: "__inference__wrapped_model_6528" - function_spec { - fullargspec { - named_tuple_value { - name: "FullArgSpec" - values { - key: "args" - value { - list_value { - } - } - } - values { - key: "varargs" - value { - string_value: "args" - } - } - values { - key: "varkw" - value { - none_value { - } - } - } - values { - key: "defaults" - value { - none_value { - } - } - } - values { - key: "kwonlyargs" - value { - list_value { - } - } - } - values { - key: "kwonlydefaults" - value { - none_value { - } - } - } - values { - key: "annotations" - value { - dict_value { - } - } - } - } - } - input_signature { - tuple_value { - values { - tensor_spec_value { - name: "input_1" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - } - } - } - } - } - nodes { - function { - concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6689" - concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6587" - concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6707" - concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6601" - function_spec { - fullargspec { - named_tuple_value { - name: "FullArgSpec" - values { - key: "args" - value { - list_value { - values { - string_value: "self" - } - values { - string_value: "inputs" - } - values { - string_value: "training" - } - values { - string_value: "mask" - } - } - } - } - values { - key: "varargs" - value { - none_value { - } - } - } - values { - key: "varkw" - value { - none_value { - } - } - } - values { - key: "defaults" - value { - list_value { - values { - bool_value: false - } - values { - none_value { - } - } - } - } - } - values { - key: "kwonlyargs" - value { - list_value { - } - } - } - values { - key: "kwonlydefaults" - value { - dict_value { - } - } - } - values { - key: "annotations" - value { - dict_value { - } - } - } - } - } - is_method: true - input_signature { - none_value { - } - } - } - } - } - nodes { - function { - concrete_functions: "__inference_dense_layer_call_fn_6754" - function_spec { - fullargspec { - named_tuple_value { - name: "FullArgSpec" - values { - key: "args" - value { - list_value { - values { - string_value: "self" - } - values { - string_value: "inputs" - } - } - } - } - values { - key: "varargs" - value { - none_value { - } - } - } - values { - key: "varkw" - value { - none_value { - } - } - } - values { - key: "defaults" - value { - none_value { - } - } - } - values { - key: "kwonlyargs" - value { - list_value { - } - } - } - values { - key: "kwonlydefaults" - value { - none_value { - } - } - } - values { - key: "annotations" - value { - dict_value { - } - } - } - } - } - is_method: true - input_signature { - none_value { - } - } - } - } - } - nodes { - function { - concrete_functions: "__inference_dense_layer_call_and_return_conditional_losses_6745" - function_spec { - fullargspec { - named_tuple_value { - name: "FullArgSpec" - values { - key: "args" - value { - list_value { - values { - string_value: "self" - } - values { - string_value: "inputs" - } - } - } - } - values { - key: "varargs" - value { - none_value { - } - } - } - values { - key: "varkw" - value { - none_value { - } - } - } - values { - key: "defaults" - value { - none_value { - } - } - } - values { - key: "kwonlyargs" - value { - list_value { - } - } - } - values { - key: "kwonlydefaults" - value { - none_value { - } - } - } - values { - key: "annotations" - value { - dict_value { - } - } - } - } - } - is_method: true - input_signature { - none_value { - } - } - } - } - } - nodes { - function { - concrete_functions: "__inference_dense_1_layer_call_fn_6773" - function_spec { - fullargspec { - named_tuple_value { - name: "FullArgSpec" - values { - key: "args" - value { - list_value { - values { - string_value: "self" - } - values { - string_value: "inputs" - } - } - } - } - values { - key: "varargs" - value { - none_value { - } - } - } - values { - key: "varkw" - value { - none_value { - } - } - } - values { - key: "defaults" - value { - none_value { - } - } - } - values { - key: "kwonlyargs" - value { - list_value { - } - } - } - values { - key: "kwonlydefaults" - value { - none_value { - } - } - } - values { - key: "annotations" - value { - dict_value { - } - } - } - } - } - is_method: true - input_signature { - none_value { - } - } - } - } - } - nodes { - function { - concrete_functions: "__inference_dense_1_layer_call_and_return_conditional_losses_6764" - function_spec { - fullargspec { - named_tuple_value { - name: "FullArgSpec" - values { - key: "args" - value { - list_value { - values { - string_value: "self" - } - values { - string_value: "inputs" - } - } - } - } - values { - key: "varargs" - value { - none_value { - } - } - } - values { - key: "varkw" - value { - none_value { - } - } - } - values { - key: "defaults" - value { - none_value { - } - } - } - values { - key: "kwonlyargs" - value { - list_value { - } - } - } - values { - key: "kwonlydefaults" - value { - none_value { - } - } - } - values { - key: "annotations" - value { - dict_value { - } - } - } - } - } - is_method: true - input_signature { - none_value { - } - } - } - } - } - nodes { - bare_concrete_function { - concrete_function_name: "__inference_signature_wrapper_6671" - argument_keywords: "input_1" - allowed_positional_arguments: 1 - } - } - concrete_functions { - key: "__inference__wrapped_model_6528" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "input_1" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - dict_value { - fields { - key: "output_1" - value { - tensor_spec_value { - name: "output_1" - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - } - } - } - } - } - concrete_functions { - key: "__inference_dense_1_layer_call_and_return_conditional_losses_6764" - value { - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "inputs" - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - dtype: DT_FLOAT - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tuple_value { - values { - tensor_spec_value { - name: "0" - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - values { - list_value { - } - } - } - } - } - } - concrete_functions { - key: "__inference_dense_1_layer_call_fn_6773" - value { - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "inputs" - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - dtype: DT_FLOAT - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tensor_spec_value { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - } - } - concrete_functions { - key: "__inference_dense_layer_call_and_return_conditional_losses_6745" - value { - bound_inputs: 9 - bound_inputs: 10 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "inputs" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tuple_value { - values { - tensor_spec_value { - name: "0" - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - dtype: DT_FLOAT - } - } - values { - list_value { - } - } - } - } - } - } - concrete_functions { - key: "__inference_dense_layer_call_fn_6754" - value { - bound_inputs: 9 - bound_inputs: 10 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "inputs" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tensor_spec_value { - shape { - dim { - size: -1 - } - dim { - size: 100 - } - } - dtype: DT_FLOAT - } - } - } - } - concrete_functions { - key: "__inference_sequential_layer_call_and_return_conditional_losses_6587" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "input_1" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - values { - bool_value: true - } - values { - none_value { - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tuple_value { - values { - tensor_spec_value { - name: "0" - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - values { - list_value { - } - } - } - } - } - } - concrete_functions { - key: "__inference_sequential_layer_call_and_return_conditional_losses_6601" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "input_1" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - values { - bool_value: false - } - values { - none_value { - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tuple_value { - values { - tensor_spec_value { - name: "0" - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - values { - list_value { - } - } - } - } - } - } - concrete_functions { - key: "__inference_sequential_layer_call_and_return_conditional_losses_6689" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "inputs" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - values { - bool_value: true - } - values { - none_value { - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tuple_value { - values { - tensor_spec_value { - name: "0" - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - values { - list_value { - } - } - } - } - } - } - concrete_functions { - key: "__inference_sequential_layer_call_and_return_conditional_losses_6707" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "inputs" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - values { - bool_value: false - } - values { - none_value { - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tuple_value { - values { - tensor_spec_value { - name: "0" - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - values { - list_value { - } - } - } - } - } - } - concrete_functions { - key: "__inference_sequential_layer_call_fn_6629" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "input_1" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - values { - bool_value: true - } - values { - none_value { - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tensor_spec_value { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - } - } - concrete_functions { - key: "__inference_sequential_layer_call_fn_6656" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "input_1" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - values { - bool_value: false - } - values { - none_value { - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tensor_spec_value { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - } - } - concrete_functions { - key: "__inference_sequential_layer_call_fn_6720" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "inputs" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - values { - bool_value: true - } - values { - none_value { - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tensor_spec_value { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - } - } - concrete_functions { - key: "__inference_sequential_layer_call_fn_6733" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - values { - tensor_spec_value { - name: "inputs" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - values { - bool_value: false - } - values { - none_value { - } - } - } - } - values { - dict_value { - } - } - } - } - output_signature { - tensor_spec_value { - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - } - } - concrete_functions { - key: "__inference_signature_wrapper_6671" - value { - bound_inputs: 9 - bound_inputs: 10 - bound_inputs: 15 - bound_inputs: 16 - canonicalized_input_signature { - tuple_value { - values { - tuple_value { - } - } - values { - dict_value { - fields { - key: "input_1" - value { - tensor_spec_value { - name: "input_1" - shape { - dim { - size: -1 - } - dim { - size: 214 - } - } - dtype: DT_INT32 - } - } - } - } - } - } - } - output_signature { - dict_value { - fields { - key: "output_1" - value { - tensor_spec_value { - name: "output_1" - shape { - dim { - size: -1 - } - dim { - size: 1 - } - } - dtype: DT_FLOAT - } - } - } - } - } - } - } - } -} - diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001 b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001 deleted file mode 100644 index 98807d26ee9f40e99330ae6a5d2988c640a320ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88424 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

+d4W!E+~y333|Hr9)dThX)0R^VOV zhg|1I4Vv(22j}KJM3#0-veVqQ({Gg}Bx$o4tKP=&4pD7Hf5I42c@^m3H@Rp)>c5p`c_-SGUWsgV7IPfSGVrlB%Mxn71pTYCj`DxLwAktB)Z z`^kFe`Pe9Whdi70yjFCkE4d)z!vr3zBf?!@P*g+~&y*bi@$0GlDz95m5U$F5@2Dfj zJCpg+wHzKf_7|oHtI{og_lRw-8l6xU3wG1287KETM(oXFTB`J(Vd_0WspdQw>ukk) zn%XijOc?gw1giam0Q+oeA1(iqR){v{@8Qe-y*f z(0lah@FGUDXC5xXJT0o=_H|RV$Yedg>CW zt4*RG`}0uWd=LD#>V@>;>C6kkFqzZ6jog#hW6ur}Qt~N*v`v0T4=PD8VPon@*^9gM zh+PrWWTVZOu4(41L_?^>+|j-3j-Wn2PjN2uD+I0kWI?HM7B~%_V>}Y_!Cy9#Jp22C zG+VbZN*7y*Q#22y|6L_b4T`{2Y7!5{LRjw=3+CH*l0ytf>|#V|*4S~d@<1c;%**BS z^~9;BvJ?&&WWl z9-rf?e$ON(-DYIK(3}~+=Lk`^r~#ihKfv%yJ19=dBzbzLIR9Q1Qr~fhG&H3{knb=P z)Rb&oDz=Wv7#jpl8-7DwffObM<-^TgR>Wjz5rYZIz|2T z^Dsy*Ng&%7CXmFfUZie8t6*i&9@0Oym*f?nVisTj2hEEr$eO1@B*69qq#NbHdb^`A z^Th@(D0vlQp7sDbCM1ESR|U9=C@|(?gzJK9U{`Ac%>n_*6dJ^TuXEAia4;Uy=F#g~ zBxt|1L;F9cahq5winL!tqpBMidRd%37`OrDL$9EmU~~rFl!j|w*ODQhZru6fD84g2 zL{kkOVCvhg#CvK14*U*fyEbm-^)-BOiTN2kqQqhB1}B93VRWIk6XJ?{_;j8WUAQ)g zDwjM%?M;IymUxk?>QbUh4uqmxM>87O+`|jq?r6qeMwhg|T>sS?v{hEcvyb0m@F*^< zd2$f#YZ7qLqtMfRBZ};6C1)>>XFqID!OgG$)l(!286>;qiy(ZVHSP1vbDz3LWnJj+C#ry?Il|t1aRtQ z5g=WBr?xtAFI?6%VOm~}L2Iu9*ioKIcI|jejvtVN&ZUVYBlRJ-x%xbjEM7*J^^}rz zy`PBq!&UT-FNLde1F-L#7vu)7;uQ@=FunX6aOXb?)QoqMxlId+)a^^Kpw*OY@;?aw zO4M<3=4td$Gb4w-?k3;*Ez!f?iP%(>kXaFxr1C`uC>2FR|KTT~y+NJ((J2KgL$3tu z{|%CB=dY4`b&|N$NQ_LrIsra3)Dz7ewNPm$fj;x~h;UB_NnIUf^arRPJi z{m5LlcX}$mtt-ZLG70ST?uYm}TZ5iAxrPVQw$lqu`=}tl7iY#6Vt7V2`klRpPOc1! zO!$cw8>+FZuabA@x=8>2cOH}emE!J-Gn6E@k<`Y6XuCEPJ1QUJq4r9=_i_rol$_14 z-_eii?qzf&-~t+7UdtZ-auWCLF2dY#r_lc3UoN&X9OKVShupjZJOedYV11Tf{ptY5 z#E-7$MGKxjaTt#udVznJ2m{~c#A`N zNW+>sus51YCW%|a%B#BM)7bZfk-Nc-*XjWOQ{H4{zX)v{sU=OD8$tYQCam{723je% zN!Afz>^K_+t_2yOa8!dFNvnpchp!pUmH!}pTY;dfqn#+VT;^PNGR(B;LUiZq3`iOX zBR7qOQTXj|(rbDNhBH5tn7qxPv|xY;Eq+wp=XMNMi%%rYDlOm~69ev3^x+7~;G6hF z(!W)RxE{%_ePKkwu9M{=Ufw3dIoXWdwAYN5|3GSrP;WJa$16=R$FF~zpF=Bow z4ZF^eE(-}d>(C2Qc1w*;+f+_^6(@p5auKPV^q7b*B+Nc-SMq(e0{O8<23WrstTI(6 z!OSs%8TXypYSmI}p0tpL@!>Qg=`&ZU^O6|bDPZTFR?ai^B3AmJ;g*J#Q;oqqAYtC{ zt3F#`rS_J|{=5iW#pLNg#sq2{@R-qjY>9EPb#QfH1p4%h&xHoi#FGed0GVL+?IWQ#Ovy=M8AmmtbyszAecwUQcFb z1;e#9*09}VZ|%o~ohada6{79jx$Aqh$g_9fx!vDaaV7s2d#A5sWWQ_JD%0D8?`HBcY!+5c|#2G|*uNPG9Q@ zKZjHk9kmT*=HD{r<4#f~MLjetTU7hEdofH92AD-K~!*X z?ZbEv-e8?Jd~Xw?_V*CY5{KdGE)K=*DYL?A56*Yc!CjjE=$1MIO=mgb>hX_hOw?nT zwnK#0Z8-_8U3KX9oFO~gu8|+T9E787sI}A2DO}YX~$k=SyQ`k$@A1tE@FP_kbN2XN3 z&Y&C04M?cjKAJP-3z0fMg%)foC2B)1^l9@*Y^k z=jlg0XU)ZL;)>94-G?rA4j>*+dPw(6Z=(3Yn3a3B0{)6mhGE``#)L&N3vUOb*^h1X zPK_5GJI$XfP~OhIcuW`{`!@3Mhz;#*)1~jHkFPuT$A_NYRzrGOd3xJ_8Eu}Mc=bt& z7Aj;UQ{`K>I61?SuHP5ScwbB5^-b=Aajsfj_lN?2elfw+=`M7~$4TtA`zMIlJ8{

3r8j?9kuMIsQx|%S`f^jW-*}C7X3% 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 !xswBeIdG!<4 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

9}7NmN#I%0%U{fvRdqTtD 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 z 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 diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index deleted file mode 100644 index c20d8afabf383430e807fde58270f4ff7c92fdc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 398 zcmbQn@*$OhfsKPviiv}fK}I0n*~8V@JHX%5FT~Nw$2H#H$;;I_B;Gy9F~Ea^U5G(p z%3@ZHEBvOMEJwl_O!%`?ixP|D6ALo+b5l!-GLwt-4fK=qOY=(f^&CS&f;^oGtXXkj%{$(r+6K}d<; zP(QgZje%hTs|n91pMdA{fb1StqZ*47qNWTcA~}hbsYUVSnI#$V<*AwJ870NK2Kq^v ziN$4W7!p{7m^e}t9?W6Yn80lMt3U99sG=CqrFp4UPZ%ONg_t?6F@jWR09BZFzuEp# zSW(z;RuKaSqe27g9*HtPHz83)iM~Pxph%7cP$i?nhxx2)b@qRrx`qJ=7(uw8ao InputsDir = unittest::getInputFileDirectory(TestMainArgv0); - llvm::sys::path::append(InputsDir, "ir2native_x86_64_model"); - return std::string(InputsDir); -} - -// Test observable behavior when no model is provided. -TEST(TFUtilsTest, NoModel) { - TFModelEvaluator Evaluator("", {}, {}); - EXPECT_FALSE(Evaluator.isValid()); -} - -// Test we can correctly load a savedmodel and evaluate it. -TEST(TFUtilsTest, LoadAndExecuteTest) { - // We use the ir2native model for test. We know it has one feature of - // dimension (1, 214) - std::vector InputNames{"serving_default_input_1"}; - std::vector OutputName{"StatefulPartitionedCall"}; - const static int64_t KnownSize = 214; - - TFModelEvaluator Evaluator(getModelPath(), InputNames, OutputName); - static const std::vector Dim{1, KnownSize}; - - EXPECT_TRUE(Evaluator.isValid()); - Evaluator.initInput(0, TF_INT32, Dim); - - int32_t *V = static_cast(TF_TensorData(Evaluator.getInput()[0])); - // Fill it up with 1's, we know the output. - for (auto I = 0; I < KnownSize; ++I) { - V[I] = 1; - } - { - auto ER = Evaluator.evaluate(); - EXPECT_TRUE(ER.hasValue()); - float Ret = *ER->getTensorValue(0); - EXPECT_EQ(static_cast(Ret), 80); - } - // The input vector should be unchanged - for (auto I = 0; I < KnownSize; ++I) { - EXPECT_EQ(V[I], 1); - } - // Zero-out the unused position '0' of the instruction histogram, which is - // after the first 9 calculated values. Should the the same result. - V[9] = 0; - { - auto ER = Evaluator.evaluate(); - EXPECT_TRUE(ER.hasValue()); - float Ret = *ER->getTensorValue(0); - EXPECT_EQ(static_cast(Ret), 80); - } -} - -// Test incorrect input setup -TEST(TFUtilsTest, EvalError) { - // We use the ir2native model for test. We know it has one feature of - // dimension (1, 214) - std::vector InputNames{"serving_default_input_1"}; - std::vector OutputName{"StatefulPartitionedCall"}; - const static int64_t KnownSize = 213; - - TFModelEvaluator Evaluator(getModelPath(), InputNames, OutputName); - static const std::vector Dim{1, KnownSize}; - - EXPECT_TRUE(Evaluator.isValid()); - Evaluator.initInput(0, TF_INT32, Dim); - - int32_t *V = static_cast(TF_TensorData(Evaluator.getInput()[0])); - // Fill it up with 1's, we know the output. - for (auto I = 0; I < KnownSize; ++I) { - V[I] = 1; - } - auto ER = Evaluator.evaluate(); - EXPECT_FALSE(ER.hasValue()); - EXPECT_FALSE(Evaluator.isValid()); -} From 4ba45a778a13eab1495a75a14682f874016f3d21 Mon Sep 17 00:00:00 2001 From: Lei Zhang Date: Sun, 12 Jul 2020 13:03:23 -0400 Subject: [PATCH 148/771] [mlir][StandardToSPIRV] Fix conversion for signed remainder Per the Vulkan's SPIR-V environment spec, "for the OpSRem and OpSMod instructions, if either operand is negative the result is undefined." So we cannot directly use spv.SRem/spv.SMod if either operand can be negative. Emulate it via spv.UMod. Because the emulation uses spv.SNegate, this commit also defines spv.SNegate. Differential Revision: https://reviews.llvm.org/D83679 --- .../mlir/Dialect/SPIRV/SPIRVArithmeticOps.td | 25 ++++++ mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td | 72 ++++++++-------- .../mlir/Dialect/SPIRV/SPIRVLogicalOps.td | 6 ++ .../ConvertStandardToSPIRV.cpp | 85 +++++++++++++++++-- mlir/lib/Dialect/SPIRV/SPIRVOps.cpp | 12 +++ .../StandardToSPIRV/std-ops-to-spirv.mlir | 42 ++++++--- .../SPIRV/Serialization/arithmetic-ops.mlir | 5 ++ mlir/test/Dialect/SPIRV/arithmetic-ops.mlir | 11 +++ 8 files changed, 204 insertions(+), 54 deletions(-) diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVArithmeticOps.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVArithmeticOps.td index 350e3659a28d7..5a12e6f36ec48 100644 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVArithmeticOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVArithmeticOps.td @@ -452,6 +452,31 @@ def SPV_SModOp : SPV_ArithmeticBinaryOp<"SMod", SPV_Integer, []> { // ----- +def SPV_SNegateOp : SPV_ArithmeticUnaryOp<"SNegate", SPV_Integer, []> { + let summary = "Signed-integer subtract of Operand from zero."; + + let description = [{ + Result Type must be a scalar or vector of integer type. + + Operand’s type must be a scalar or vector of integer type. It must + have the same number of components as Result Type. The component width + must equal the component width in Result Type. + + Results are computed per component. + + + + #### Example: + + ```mlir + %1 = spv.SNegate %0 : i32 + %3 = spv.SNegate %2 : vector<4xi32> + ``` + }]; +} + +// ----- + def SPV_SRemOp : SPV_ArithmeticBinaryOp<"SRem", SPV_Integer, []> { let summary = [{ Signed remainder operation for the remainder whose sign matches the sign diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td index f114c878569d6..cbff82efdfd3f 100644 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td @@ -3150,6 +3150,7 @@ def SPV_OC_OpUConvert : I32EnumAttrCase<"OpUConvert", 113>; def SPV_OC_OpSConvert : I32EnumAttrCase<"OpSConvert", 114>; def SPV_OC_OpFConvert : I32EnumAttrCase<"OpFConvert", 115>; def SPV_OC_OpBitcast : I32EnumAttrCase<"OpBitcast", 124>; +def SPV_OC_OpSNegate : I32EnumAttrCase<"OpSNegate", 126>; def SPV_OC_OpFNegate : I32EnumAttrCase<"OpFNegate", 127>; def SPV_OC_OpIAdd : I32EnumAttrCase<"OpIAdd", 128>; def SPV_OC_OpFAdd : I32EnumAttrCase<"OpFAdd", 129>; @@ -3271,41 +3272,42 @@ def SPV_OpcodeAttr : SPV_OC_OpCompositeInsert, SPV_OC_OpTranspose, SPV_OC_OpConvertFToU, SPV_OC_OpConvertFToS, SPV_OC_OpConvertSToF, SPV_OC_OpConvertUToF, SPV_OC_OpUConvert, SPV_OC_OpSConvert, SPV_OC_OpFConvert, SPV_OC_OpBitcast, - SPV_OC_OpFNegate, SPV_OC_OpIAdd, SPV_OC_OpFAdd, SPV_OC_OpISub, SPV_OC_OpFSub, - SPV_OC_OpIMul, SPV_OC_OpFMul, SPV_OC_OpUDiv, SPV_OC_OpSDiv, SPV_OC_OpFDiv, - SPV_OC_OpUMod, SPV_OC_OpSRem, SPV_OC_OpSMod, SPV_OC_OpFRem, SPV_OC_OpFMod, - SPV_OC_OpMatrixTimesScalar, SPV_OC_OpMatrixTimesMatrix, SPV_OC_OpLogicalEqual, - SPV_OC_OpLogicalNotEqual, SPV_OC_OpLogicalOr, SPV_OC_OpLogicalAnd, - SPV_OC_OpLogicalNot, SPV_OC_OpSelect, SPV_OC_OpIEqual, SPV_OC_OpINotEqual, - SPV_OC_OpUGreaterThan, SPV_OC_OpSGreaterThan, SPV_OC_OpUGreaterThanEqual, - SPV_OC_OpSGreaterThanEqual, SPV_OC_OpULessThan, SPV_OC_OpSLessThan, - SPV_OC_OpULessThanEqual, SPV_OC_OpSLessThanEqual, SPV_OC_OpFOrdEqual, - SPV_OC_OpFUnordEqual, SPV_OC_OpFOrdNotEqual, SPV_OC_OpFUnordNotEqual, - SPV_OC_OpFOrdLessThan, SPV_OC_OpFUnordLessThan, SPV_OC_OpFOrdGreaterThan, - SPV_OC_OpFUnordGreaterThan, SPV_OC_OpFOrdLessThanEqual, - SPV_OC_OpFUnordLessThanEqual, SPV_OC_OpFOrdGreaterThanEqual, - SPV_OC_OpFUnordGreaterThanEqual, SPV_OC_OpShiftRightLogical, - SPV_OC_OpShiftRightArithmetic, SPV_OC_OpShiftLeftLogical, SPV_OC_OpBitwiseOr, - SPV_OC_OpBitwiseXor, SPV_OC_OpBitwiseAnd, SPV_OC_OpNot, - SPV_OC_OpBitFieldInsert, SPV_OC_OpBitFieldSExtract, SPV_OC_OpBitFieldUExtract, - SPV_OC_OpBitReverse, SPV_OC_OpBitCount, SPV_OC_OpControlBarrier, - SPV_OC_OpMemoryBarrier, SPV_OC_OpAtomicCompareExchangeWeak, - SPV_OC_OpAtomicIIncrement, SPV_OC_OpAtomicIDecrement, SPV_OC_OpAtomicIAdd, - SPV_OC_OpAtomicISub, SPV_OC_OpAtomicSMin, SPV_OC_OpAtomicUMin, - SPV_OC_OpAtomicSMax, SPV_OC_OpAtomicUMax, SPV_OC_OpAtomicAnd, - SPV_OC_OpAtomicOr, SPV_OC_OpAtomicXor, SPV_OC_OpPhi, SPV_OC_OpLoopMerge, - SPV_OC_OpSelectionMerge, SPV_OC_OpLabel, SPV_OC_OpBranch, - SPV_OC_OpBranchConditional, SPV_OC_OpReturn, SPV_OC_OpReturnValue, - SPV_OC_OpUnreachable, SPV_OC_OpNoLine, SPV_OC_OpModuleProcessed, - SPV_OC_OpGroupNonUniformElect, SPV_OC_OpGroupNonUniformBallot, - SPV_OC_OpGroupNonUniformIAdd, SPV_OC_OpGroupNonUniformFAdd, - SPV_OC_OpGroupNonUniformIMul, SPV_OC_OpGroupNonUniformFMul, - SPV_OC_OpGroupNonUniformSMin, SPV_OC_OpGroupNonUniformUMin, - SPV_OC_OpGroupNonUniformFMin, SPV_OC_OpGroupNonUniformSMax, - SPV_OC_OpGroupNonUniformUMax, SPV_OC_OpGroupNonUniformFMax, - SPV_OC_OpSubgroupBallotKHR, SPV_OC_OpTypeCooperativeMatrixNV, - SPV_OC_OpCooperativeMatrixLoadNV, SPV_OC_OpCooperativeMatrixStoreNV, - SPV_OC_OpCooperativeMatrixMulAddNV, SPV_OC_OpCooperativeMatrixLengthNV + SPV_OC_OpSNegate, SPV_OC_OpFNegate, SPV_OC_OpIAdd, SPV_OC_OpFAdd, + SPV_OC_OpISub, SPV_OC_OpFSub, SPV_OC_OpIMul, SPV_OC_OpFMul, SPV_OC_OpUDiv, + SPV_OC_OpSDiv, SPV_OC_OpFDiv, SPV_OC_OpUMod, SPV_OC_OpSRem, SPV_OC_OpSMod, + SPV_OC_OpFRem, SPV_OC_OpFMod, SPV_OC_OpMatrixTimesScalar, + SPV_OC_OpMatrixTimesMatrix, SPV_OC_OpLogicalEqual, SPV_OC_OpLogicalNotEqual, + SPV_OC_OpLogicalOr, SPV_OC_OpLogicalAnd, SPV_OC_OpLogicalNot, SPV_OC_OpSelect, + SPV_OC_OpIEqual, SPV_OC_OpINotEqual, SPV_OC_OpUGreaterThan, + SPV_OC_OpSGreaterThan, SPV_OC_OpUGreaterThanEqual, SPV_OC_OpSGreaterThanEqual, + SPV_OC_OpULessThan, SPV_OC_OpSLessThan, SPV_OC_OpULessThanEqual, + SPV_OC_OpSLessThanEqual, SPV_OC_OpFOrdEqual, SPV_OC_OpFUnordEqual, + SPV_OC_OpFOrdNotEqual, SPV_OC_OpFUnordNotEqual, SPV_OC_OpFOrdLessThan, + SPV_OC_OpFUnordLessThan, SPV_OC_OpFOrdGreaterThan, SPV_OC_OpFUnordGreaterThan, + SPV_OC_OpFOrdLessThanEqual, SPV_OC_OpFUnordLessThanEqual, + SPV_OC_OpFOrdGreaterThanEqual, SPV_OC_OpFUnordGreaterThanEqual, + SPV_OC_OpShiftRightLogical, SPV_OC_OpShiftRightArithmetic, + SPV_OC_OpShiftLeftLogical, SPV_OC_OpBitwiseOr, SPV_OC_OpBitwiseXor, + SPV_OC_OpBitwiseAnd, SPV_OC_OpNot, SPV_OC_OpBitFieldInsert, + SPV_OC_OpBitFieldSExtract, SPV_OC_OpBitFieldUExtract, SPV_OC_OpBitReverse, + SPV_OC_OpBitCount, SPV_OC_OpControlBarrier, SPV_OC_OpMemoryBarrier, + SPV_OC_OpAtomicCompareExchangeWeak, SPV_OC_OpAtomicIIncrement, + SPV_OC_OpAtomicIDecrement, SPV_OC_OpAtomicIAdd, SPV_OC_OpAtomicISub, + SPV_OC_OpAtomicSMin, SPV_OC_OpAtomicUMin, SPV_OC_OpAtomicSMax, + SPV_OC_OpAtomicUMax, SPV_OC_OpAtomicAnd, SPV_OC_OpAtomicOr, SPV_OC_OpAtomicXor, + SPV_OC_OpPhi, SPV_OC_OpLoopMerge, SPV_OC_OpSelectionMerge, SPV_OC_OpLabel, + SPV_OC_OpBranch, SPV_OC_OpBranchConditional, SPV_OC_OpReturn, + SPV_OC_OpReturnValue, SPV_OC_OpUnreachable, SPV_OC_OpNoLine, + SPV_OC_OpModuleProcessed, SPV_OC_OpGroupNonUniformElect, + SPV_OC_OpGroupNonUniformBallot, SPV_OC_OpGroupNonUniformIAdd, + SPV_OC_OpGroupNonUniformFAdd, SPV_OC_OpGroupNonUniformIMul, + SPV_OC_OpGroupNonUniformFMul, SPV_OC_OpGroupNonUniformSMin, + SPV_OC_OpGroupNonUniformUMin, SPV_OC_OpGroupNonUniformFMin, + SPV_OC_OpGroupNonUniformSMax, SPV_OC_OpGroupNonUniformUMax, + SPV_OC_OpGroupNonUniformFMax, SPV_OC_OpSubgroupBallotKHR, + SPV_OC_OpTypeCooperativeMatrixNV, SPV_OC_OpCooperativeMatrixLoadNV, + SPV_OC_OpCooperativeMatrixStoreNV, SPV_OC_OpCooperativeMatrixMulAddNV, + SPV_OC_OpCooperativeMatrixLengthNV ]>; // End opcode section. Generated from SPIR-V spec; DO NOT MODIFY! diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVLogicalOps.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVLogicalOps.td index e1b477126a02f..9789122809ec6 100644 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVLogicalOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVLogicalOps.td @@ -26,6 +26,12 @@ class SPV_LogicalBinaryOp { let parser = [{ return ::parseLogicalBinaryOp(parser, result); }]; let printer = [{ return ::printLogicalOp(getOperation(), p); }]; + + let builders = [ + OpBuilder< + "OpBuilder &builder, OperationState &state, Value lhs, Value rhs", + "::buildLogicalBinaryOp(builder, state, lhs, rhs);"> + ]; } class SPV_LogicalUnaryOp(loc, type, lhs); + Value rhsAbs = builder.create(loc, type, rhs); + Value abs = builder.create(loc, lhsAbs, rhsAbs); + + // Fix the sign. + Value isPositive; + if (lhs == signOperand) + isPositive = builder.create(loc, lhs, lhsAbs); + else + isPositive = builder.create(loc, rhs, rhsAbs); + Value absNegate = builder.create(loc, type, abs); + return builder.create(loc, type, isPositive, abs, absNegate); +} + /// Returns the offset of the value in `targetBits` representation. `srcIdx` is /// an index into a 1-D array with each element having `sourceBits`. When /// accessing an element in the array treating as having elements of @@ -308,6 +337,19 @@ class UnaryAndBinaryOpPattern final : public SPIRVOpLowering { } }; +/// Converts std.remi_signed to SPIR-V ops. +/// +/// This cannot be merged into the template unary/binary pattern due to +/// Vulkan restrictions over spv.SRem and spv.SMod. +class SignedRemIOpPattern final : public SPIRVOpLowering { +public: + using SPIRVOpLowering::SPIRVOpLowering; + + LogicalResult + matchAndRewrite(SignedRemIOp remOp, ArrayRef operands, + ConversionPatternRewriter &rewriter) const override; +}; + /// Converts bitwise standard operations to SPIR-V operations. This is a special /// pattern other than the BinaryOpPatternPattern because if the operands are /// boolean values, SPIR-V uses different operations (`SPIRVLogicalOp`). For @@ -506,6 +548,20 @@ class XOrOpPattern final : public SPIRVOpLowering { } // namespace +//===----------------------------------------------------------------------===// +// SignedRemIOpPattern +//===----------------------------------------------------------------------===// + +LogicalResult SignedRemIOpPattern::matchAndRewrite( + SignedRemIOp remOp, ArrayRef operands, + ConversionPatternRewriter &rewriter) const { + Value result = emulateSignedRemainder(remOp.getLoc(), operands[0], + operands[1], operands[0], rewriter); + rewriter.replaceOp(remOp, result); + + return success(); +} + //===----------------------------------------------------------------------===// // ConstantOp with composite type. //===----------------------------------------------------------------------===// @@ -1005,6 +1061,9 @@ void populateStandardToSPIRVPatterns(MLIRContext *context, SPIRVTypeConverter &typeConverter, OwningRewritePatternList &patterns) { patterns.insert< + // Unary and binary patterns + BitwiseOpPattern, + BitwiseOpPattern, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, @@ -1020,7 +1079,6 @@ void populateStandardToSPIRVPatterns(MLIRContext *context, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, - UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, @@ -1031,19 +1089,28 @@ void populateStandardToSPIRVPatterns(MLIRContext *context, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, UnaryAndBinaryOpPattern, - AllocOpPattern, DeallocOpPattern, - BitwiseOpPattern, - BitwiseOpPattern, - BoolCmpIOpPattern, ConstantCompositeOpPattern, ConstantScalarOpPattern, - CmpFOpPattern, CmpIOpPattern, IntLoadOpPattern, LoadOpPattern, - ReturnOpPattern, SelectOpPattern, IntStoreOpPattern, StoreOpPattern, + SignedRemIOpPattern, XOrOpPattern, + + // Comparison patterns + BoolCmpIOpPattern, CmpFOpPattern, CmpIOpPattern, + + // Constant patterns + ConstantCompositeOpPattern, ConstantScalarOpPattern, + + // Memory patterns + AllocOpPattern, DeallocOpPattern, IntLoadOpPattern, IntStoreOpPattern, + LoadOpPattern, StoreOpPattern, + + ReturnOpPattern, SelectOpPattern, + + // Type cast patterns ZeroExtendI1Pattern, TypeCastingOpPattern, TypeCastingOpPattern, TypeCastingOpPattern, TypeCastingOpPattern, TypeCastingOpPattern, TypeCastingOpPattern, - TypeCastingOpPattern, XOrOpPattern>( - context, typeConverter); + TypeCastingOpPattern>(context, + typeConverter); } } // namespace mlir diff --git a/mlir/lib/Dialect/SPIRV/SPIRVOps.cpp b/mlir/lib/Dialect/SPIRV/SPIRVOps.cpp index 6c8319224974a..9d0570257d422 100644 --- a/mlir/lib/Dialect/SPIRV/SPIRVOps.cpp +++ b/mlir/lib/Dialect/SPIRV/SPIRVOps.cpp @@ -844,6 +844,18 @@ static LogicalResult verifyShiftOp(Operation *op) { return success(); } +static void buildLogicalBinaryOp(OpBuilder &builder, OperationState &state, + Value lhs, Value rhs) { + assert(lhs.getType() == rhs.getType()); + + Type boolType = builder.getI1Type(); + if (auto vecType = lhs.getType().dyn_cast()) + boolType = VectorType::get(vecType.getShape(), boolType); + state.addTypes(boolType); + + state.addOperands({lhs, rhs}); +} + //===----------------------------------------------------------------------===// // spv.AccessChainOp //===----------------------------------------------------------------------===// diff --git a/mlir/test/Conversion/StandardToSPIRV/std-ops-to-spirv.mlir b/mlir/test/Conversion/StandardToSPIRV/std-ops-to-spirv.mlir index c232395d80db5..a93bf792b34f3 100644 --- a/mlir/test/Conversion/StandardToSPIRV/std-ops-to-spirv.mlir +++ b/mlir/test/Conversion/StandardToSPIRV/std-ops-to-spirv.mlir @@ -22,12 +22,23 @@ func @int32_scalar(%lhs: i32, %rhs: i32) { %2 = muli %lhs, %rhs: i32 // CHECK: spv.SDiv %{{.*}}, %{{.*}}: i32 %3 = divi_signed %lhs, %rhs: i32 - // CHECK: spv.SRem %{{.*}}, %{{.*}}: i32 - %4 = remi_signed %lhs, %rhs: i32 // CHECK: spv.UDiv %{{.*}}, %{{.*}}: i32 - %5 = divi_unsigned %lhs, %rhs: i32 + %4 = divi_unsigned %lhs, %rhs: i32 // CHECK: spv.UMod %{{.*}}, %{{.*}}: i32 - %6 = remi_unsigned %lhs, %rhs: i32 + %5 = remi_unsigned %lhs, %rhs: i32 + return +} + +// CHECK-LABEL: @scalar_srem +// CHECK-SAME: (%[[LHS:.+]]: i32, %[[RHS:.+]]: i32) +func @scalar_srem(%lhs: i32, %rhs: i32) { + // CHECK: %[[LABS:.+]] = spv.GLSL.SAbs %[[LHS]] : i32 + // CHECK: %[[RABS:.+]] = spv.GLSL.SAbs %[[RHS]] : i32 + // CHECK: %[[ABS:.+]] = spv.UMod %[[LABS]], %[[RABS]] : i32 + // CHECK: %[[POS:.+]] = spv.IEqual %[[LHS]], %[[LABS]] : i32 + // CHECK: %[[NEG:.+]] = spv.SNegate %[[ABS]] : i32 + // CHECK: %{{.+}} = spv.Select %[[POS]], %[[ABS]], %[[NEG]] : i1, i32 + %0 = remi_signed %lhs, %rhs: i32 return } @@ -75,13 +86,24 @@ func @float32_binary_scalar(%lhs: f32, %rhs: f32) { // Check int vector types. // CHECK-LABEL: @int_vector234 -func @int_vector234(%arg0: vector<2xi8>, %arg1: vector<3xi16>, %arg2: vector<4xi64>) { +func @int_vector234(%arg0: vector<2xi8>, %arg1: vector<4xi64>) { // CHECK: spv.SDiv %{{.*}}, %{{.*}}: vector<2xi8> %0 = divi_signed %arg0, %arg0: vector<2xi8> - // CHECK: spv.SRem %{{.*}}, %{{.*}}: vector<3xi16> - %1 = remi_signed %arg1, %arg1: vector<3xi16> // CHECK: spv.UDiv %{{.*}}, %{{.*}}: vector<4xi64> - %2 = divi_unsigned %arg2, %arg2: vector<4xi64> + %1 = divi_unsigned %arg1, %arg1: vector<4xi64> + return +} + +// CHECK-LABEL: @vector_srem +// CHECK-SAME: (%[[LHS:.+]]: vector<3xi16>, %[[RHS:.+]]: vector<3xi16>) +func @vector_srem(%arg0: vector<3xi16>, %arg1: vector<3xi16>) { + // CHECK: %[[LABS:.+]] = spv.GLSL.SAbs %[[LHS]] : vector<3xi16> + // CHECK: %[[RABS:.+]] = spv.GLSL.SAbs %[[RHS]] : vector<3xi16> + // CHECK: %[[ABS:.+]] = spv.UMod %[[LABS]], %[[RABS]] : vector<3xi16> + // CHECK: %[[POS:.+]] = spv.IEqual %[[LHS]], %[[LABS]] : vector<3xi16> + // CHECK: %[[NEG:.+]] = spv.SNegate %[[ABS]] : vector<3xi16> + // CHECK: %{{.+}} = spv.Select %[[POS]], %[[ABS]], %[[NEG]] : vector<3xi1>, vector<3xi16> + %0 = remi_signed %arg0, %arg1: vector<3xi16> return } @@ -132,8 +154,8 @@ module attributes { func @int_vector23(%arg0: vector<2xi8>, %arg1: vector<3xi16>) { // CHECK: spv.SDiv %{{.*}}, %{{.*}}: vector<2xi32> %0 = divi_signed %arg0, %arg0: vector<2xi8> - // CHECK: spv.SRem %{{.*}}, %{{.*}}: vector<3xi32> - %1 = remi_signed %arg1, %arg1: vector<3xi16> + // CHECK: spv.SDiv %{{.*}}, %{{.*}}: vector<3xi32> + %1 = divi_signed %arg1, %arg1: vector<3xi16> return } diff --git a/mlir/test/Dialect/SPIRV/Serialization/arithmetic-ops.mlir b/mlir/test/Dialect/SPIRV/Serialization/arithmetic-ops.mlir index 55c67dafe6bba..9752c0d0e5799 100644 --- a/mlir/test/Dialect/SPIRV/Serialization/arithmetic-ops.mlir +++ b/mlir/test/Dialect/SPIRV/Serialization/arithmetic-ops.mlir @@ -71,6 +71,11 @@ spv.module Logical GLSL450 requires #spv.vce { %0 = spv.SMod %arg0, %arg1 : vector<4xi32> spv.Return } + spv.func @snegate(%arg0 : vector<4xi32>) "None" { + // CHECK: {{%.*}} = spv.SNegate {{%.*}} : vector<4xi32> + %0 = spv.SNegate %arg0 : vector<4xi32> + spv.Return + } spv.func @srem(%arg0 : vector<4xi32>, %arg1 : vector<4xi32>) "None" { // CHECK: {{%.*}} = spv.SRem {{%.*}}, {{%.*}} : vector<4xi32> %0 = spv.SRem %arg0, %arg1 : vector<4xi32> diff --git a/mlir/test/Dialect/SPIRV/arithmetic-ops.mlir b/mlir/test/Dialect/SPIRV/arithmetic-ops.mlir index 85998fb03efdd..de574b1510c9c 100644 --- a/mlir/test/Dialect/SPIRV/arithmetic-ops.mlir +++ b/mlir/test/Dialect/SPIRV/arithmetic-ops.mlir @@ -174,6 +174,17 @@ func @smod_scalar(%arg: i32) -> i32 { // ----- +//===----------------------------------------------------------------------===// +// spv.SNegate +//===----------------------------------------------------------------------===// + +func @snegate_scalar(%arg: i32) -> i32 { + // CHECK: spv.SNegate + %0 = spv.SNegate %arg : i32 + return %0 : i32 +} + +// ----- //===----------------------------------------------------------------------===// // spv.SRem //===----------------------------------------------------------------------===// From 540277d08440048c5f3239ff7bcc95a505142d82 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Mon, 13 Jul 2020 20:18:59 +0000 Subject: [PATCH 149/771] [gn build] Port 9908a3b9f52 --- llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn | 1 - llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn | 1 - 2 files changed, 2 deletions(-) diff --git a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn index c13dc723ecd1b..11498ed602984 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Analysis/BUILD.gn @@ -55,7 +55,6 @@ static_library("Analysis") { "InlineAdvisor.cpp", "InlineCost.cpp", "InlineFeaturesAnalysis.cpp", - "InlineSizeEstimatorAnalysis.cpp", "InstCount.cpp", "InstructionPrecedenceTracking.cpp", "InstructionSimplify.cpp", diff --git a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn index 27733f63c2c50..b0dcd497d844e 100644 --- a/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/unittests/Analysis/BUILD.gn @@ -25,7 +25,6 @@ unittest("AnalysisTests") { "GlobalsModRefTest.cpp", "IVDescriptorsTest.cpp", "InlineFeaturesAnalysisTest.cpp", - "InlineSizeEstimatorAnalysisTest.cpp", "LazyCallGraphTest.cpp", "LoadsTest.cpp", "LoopInfoTest.cpp", From 2f23270af9bbe87859dc228eca63ccbc8986bebd Mon Sep 17 00:00:00 2001 From: Thomas Raoux Date: Mon, 13 Jul 2020 13:24:27 -0700 Subject: [PATCH 150/771] [mlir] Support operations with multiple results in slicing Right now slicing would assert if an operation with multiple results is in the slice. Differential Revision: https://reviews.llvm.org/D83627 --- mlir/lib/Analysis/SliceAnalysis.cpp | 36 +++++++++------------ mlir/test/Dialect/Affine/slicing-utils.mlir | 11 +++++++ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/mlir/lib/Analysis/SliceAnalysis.cpp b/mlir/lib/Analysis/SliceAnalysis.cpp index a09fcf4bea068..8f5f87ba620ee 100644 --- a/mlir/lib/Analysis/SliceAnalysis.cpp +++ b/mlir/lib/Analysis/SliceAnalysis.cpp @@ -41,24 +41,23 @@ static void getForwardSliceImpl(Operation *op, } if (auto forOp = dyn_cast(op)) { - for (auto *ownerOp : forOp.getInductionVar().getUsers()) - if (forwardSlice->count(ownerOp) == 0) - getForwardSliceImpl(ownerOp, forwardSlice, filter); + for (Operation *userOp : forOp.getInductionVar().getUsers()) + if (forwardSlice->count(userOp) == 0) + getForwardSliceImpl(userOp, forwardSlice, filter); } else if (auto forOp = dyn_cast(op)) { - for (auto *ownerOp : forOp.getInductionVar().getUsers()) - if (forwardSlice->count(ownerOp) == 0) - getForwardSliceImpl(ownerOp, forwardSlice, filter); - for (auto result : forOp.getResults()) - for (auto *ownerOp : result.getUsers()) - if (forwardSlice->count(ownerOp) == 0) - getForwardSliceImpl(ownerOp, forwardSlice, filter); + for (Operation *userOp : forOp.getInductionVar().getUsers()) + if (forwardSlice->count(userOp) == 0) + getForwardSliceImpl(userOp, forwardSlice, filter); + for (Value result : forOp.getResults()) + for (Operation *userOp : result.getUsers()) + if (forwardSlice->count(userOp) == 0) + getForwardSliceImpl(userOp, forwardSlice, filter); } else { assert(op->getNumRegions() == 0 && "unexpected generic op with regions"); - assert(op->getNumResults() <= 1 && "unexpected multiple results"); - if (op->getNumResults() > 0) { - for (auto *ownerOp : op->getResult(0).getUsers()) - if (forwardSlice->count(ownerOp) == 0) - getForwardSliceImpl(ownerOp, forwardSlice, filter); + for (Value result : op->getResults()) { + for (Operation *userOp : result.getUsers()) + if (forwardSlice->count(userOp) == 0) + getForwardSliceImpl(userOp, forwardSlice, filter); } } @@ -172,12 +171,9 @@ struct DFSState { } // namespace static void DFSPostorder(Operation *current, DFSState *state) { - assert(current->getNumResults() <= 1 && "NYI: multi-result"); - if (current->getNumResults() > 0) { - for (auto &u : current->getResult(0).getUses()) { - auto *op = u.getOwner(); + for (Value result : current->getResults()) { + for (Operation *op : result.getUsers()) DFSPostorder(op, state); - } } bool inserted; using IterTy = decltype(state->seen.begin()); diff --git a/mlir/test/Dialect/Affine/slicing-utils.mlir b/mlir/test/Dialect/Affine/slicing-utils.mlir index 5cc0c3ddcdfb2..e11a66b0d0ebb 100644 --- a/mlir/test/Dialect/Affine/slicing-utils.mlir +++ b/mlir/test/Dialect/Affine/slicing-utils.mlir @@ -274,6 +274,17 @@ func @slicing_test_function_argument(%arg0: index) -> index { return %0 : index } +// FWD-LABEL: slicing_test_multiple_return +// BWD-LABEL: slicing_test_multiple_return +// FWDBWD-LABEL: slicing_test_multiple_return +func @slicing_test_multiple_return(%arg0: index) -> (index, index) { + // BWD: matched: {{.*}} (index, index) -> (index, index) backward static slice: + // FWD: matched: %{{.*}}:2 = "slicing-test-op"(%arg0, %arg0) : (index, index) -> (index, index) forward static slice: + // FWD: return %{{.*}}#0, %{{.*}}#1 : index, index + %0:2 = "slicing-test-op"(%arg0, %arg0): (index, index) -> (index, index) + return %0#0, %0#1 : index, index +} + // This test dumps 2 sets of outputs: first the test outputs themselves followed // by the module. These labels isolate the test outputs from the module dump. // FWD-LABEL: slicing_test From f630b8590f0c541ccc8133d84f9464c2b469dda3 Mon Sep 17 00:00:00 2001 From: AlexisPerry Date: Mon, 13 Jul 2020 10:32:12 -0600 Subject: [PATCH 151/771] [flang] Extended the flang driver options to include gfortran equivalents to pgf90 specific options. Summary: Added gfortran equivalents of pgf90's -Mfixed, -Mfree, -Mextend, -Mstandard, -Munlimited and also added -fdefault-double-8 Reviewers: sscalpone, richard.barton.arm, DavidTruby, clementval, jdoerfert Reviewed By: sscalpone, richard.barton.arm Subscribers: sstefan1, llvm-commits, flang-commits Tags: #llvm, #flang Differential Revision: https://reviews.llvm.org/D83687 --- flang/tools/f18/f18.cpp | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/flang/tools/f18/f18.cpp b/flang/tools/f18/f18.cpp index 26682eaa64897..05766a9c6a6dc 100644 --- a/flang/tools/f18/f18.cpp +++ b/flang/tools/f18/f18.cpp @@ -446,15 +446,17 @@ int main(int argc, char *const argv[]) { args.pop_front(); } break; - } else if (arg == "-Mfixed") { + } else if (arg == "-Mfixed" || arg == "-ffixed-form") { driver.forcedForm = true; options.isFixedForm = true; - } else if (arg == "-Mfree") { + } else if (arg == "-Mfree" || arg == "-ffree-form") { driver.forcedForm = true; options.isFixedForm = false; - } else if (arg == "-Mextend") { + } else if (arg == "-Mextend" || arg == "-ffixed-line-length-132") { options.fixedFormColumns = 132; - } else if (arg == "-Munlimited") { + } else if (arg == "-Munlimited" || arg == "-ffree-line-length-none" || + arg == "-ffree-line-length-0" || arg == "-ffixed-line-length-none" || + arg == "-ffixed-line-length-0") { // For reparsing f18's -E output of fixed-form cooked character stream options.fixedFormColumns = 1000000; } else if (arg == "-Mbackslash") { @@ -463,7 +465,8 @@ int main(int argc, char *const argv[]) { } else if (arg == "-Mnobackslash") { options.features.Enable( Fortran::common::LanguageFeature::BackslashEscapes, true); - } else if (arg == "-Mstandard") { + } else if (arg == "-Mstandard" || arg == "-std=f95" || + arg == "-std=f2003" || arg == "-std=f2008" || arg == "-std=legacy") { driver.warnOnNonstandardUsage = true; } else if (arg == "-fopenmp") { options.features.Enable(Fortran::common::LanguageFeature::OpenMP); @@ -530,6 +533,8 @@ int main(int argc, char *const argv[]) { } else if (arg.substr(0, 2) == "-U") { options.predefinitions.emplace_back( arg.substr(2), std::optional{}); + } else if (arg == "-fdefault-double-8") { + defaultKinds.set_defaultRealKind(4); } else if (arg == "-r8" || arg == "-fdefault-real-8") { defaultKinds.set_defaultRealKind(8); } else if (arg == "-i8" || arg == "-fdefault-integer-8") { @@ -580,15 +585,17 @@ int main(int argc, char *const argv[]) { } else if (arg == "-help" || arg == "--help" || arg == "-?") { llvm::errs() << "f18 options:\n" - << " -Mfixed | -Mfree force the source form\n" - << " -Mextend 132-column fixed form\n" + << " -Mfixed | -Mfree | -ffixed-form | -ffree-form force the " + "source form\n" + << " -Mextend | -ffixed-line-length-132 132-column fixed form\n" << " -f[no-]backslash enable[disable] \\escapes in literals\n" << " -M[no]backslash disable[enable] \\escapes in literals\n" << " -Mstandard enable conformance warnings\n" + << " -std= enable conformance warnings\n" << " -fenable= enable a language feature\n" << " -fdisable= disable a language feature\n" - << " -r8 | -fdefault-real-8 | -i8 | -fdefault-integer-8 " - "change default kinds of intrinsic types\n" + << " -r8 | -fdefault-real-8 | -i8 | -fdefault-integer-8 | " + "-fdefault-double-8 change default kinds of intrinsic types\n" << " -Werror treat warnings as errors\n" << " -ed enable fixed form D lines\n" << " -E prescan & preprocess only\n" @@ -632,21 +639,26 @@ int main(int argc, char *const argv[]) { if (driver.warnOnNonstandardUsage) { options.features.WarnOnAllNonstandard(); } - if (options.features.IsEnabled(Fortran::common::LanguageFeature::OpenMP)) { - driver.pgf90Args.push_back("-mp"); - } if (isPGF90) { if (!options.features.IsEnabled( Fortran::common::LanguageFeature::BackslashEscapes)) { driver.pgf90Args.push_back( "-Mbackslash"); // yes, this *disables* them in pgf90 } + if (options.features.IsEnabled(Fortran::common::LanguageFeature::OpenMP)) { + driver.pgf90Args.push_back("-mp"); + } + Fortran::parser::useHexadecimalEscapeSequences = false; } else { if (options.features.IsEnabled( Fortran::common::LanguageFeature::BackslashEscapes)) { driver.pgf90Args.push_back("-fbackslash"); } + if (options.features.IsEnabled(Fortran::common::LanguageFeature::OpenMP)) { + driver.pgf90Args.push_back("-fopenmp"); + } + Fortran::parser::useHexadecimalEscapeSequences = true; } From 0d988da6d13e16a397d58bc3b965a36adb7fee03 Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Mon, 13 Jul 2020 11:20:27 -0700 Subject: [PATCH 152/771] [MLIR] Change ODS collective params build method to provide an empty default value for named attributes - Provide default value for `ArrayRef attributes` parameter of the collective params build method. - Change the `genSeparateArgParamBuilder` function to not generate build methods that may be ambiguous with the new collective params build method. - This change should help eliminate passing empty NamedAttribue ArrayRef when the collective params build method is used - Extend op-decl.td unit test to make sure the ambiguous build methods are not generated. Differential Revision: https://reviews.llvm.org/D83517 --- .../ConvertStandardToSPIRV.cpp | 18 +++---- mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp | 7 ++- mlir/test/mlir-tblgen/op-decl.td | 50 +++++++++++++++++ mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp | 53 ++++++++++++++++--- 4 files changed, 108 insertions(+), 20 deletions(-) diff --git a/mlir/lib/Conversion/StandardToSPIRV/ConvertStandardToSPIRV.cpp b/mlir/lib/Conversion/StandardToSPIRV/ConvertStandardToSPIRV.cpp index dad8bfc0173f2..e59830fcef89a 100644 --- a/mlir/lib/Conversion/StandardToSPIRV/ConvertStandardToSPIRV.cpp +++ b/mlir/lib/Conversion/StandardToSPIRV/ConvertStandardToSPIRV.cpp @@ -331,8 +331,7 @@ class UnaryAndBinaryOpPattern final : public SPIRVOpLowering { return operation.emitError( "bitwidth emulation is not implemented yet on unsigned op"); } - rewriter.template replaceOpWithNewOp(operation, dstType, operands, - ArrayRef()); + rewriter.template replaceOpWithNewOp(operation, dstType, operands); return success(); } }; @@ -368,11 +367,11 @@ class BitwiseOpPattern final : public SPIRVOpLowering { if (!dstType) return failure(); if (isBoolScalarOrVector(operands.front().getType())) { - rewriter.template replaceOpWithNewOp( - operation, dstType, operands, ArrayRef()); + rewriter.template replaceOpWithNewOp(operation, dstType, + operands); } else { - rewriter.template replaceOpWithNewOp( - operation, dstType, operands, ArrayRef()); + rewriter.template replaceOpWithNewOp(operation, dstType, + operands); } return success(); } @@ -529,8 +528,8 @@ class TypeCastingOpPattern final : public SPIRVOpLowering { // Then we can just erase this operation by forwarding its operand. rewriter.replaceOp(operation, operands.front()); } else { - rewriter.template replaceOpWithNewOp( - operation, dstType, operands, ArrayRef()); + rewriter.template replaceOpWithNewOp(operation, dstType, + operands); } return success(); } @@ -1046,8 +1045,7 @@ XOrOpPattern::matchAndRewrite(XOrOp xorOp, ArrayRef operands, auto dstType = typeConverter.convertType(xorOp.getType()); if (!dstType) return failure(); - rewriter.replaceOpWithNewOp(xorOp, dstType, operands, - ArrayRef()); + rewriter.replaceOpWithNewOp(xorOp, dstType, operands); return success(); } diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp index 7aa26541ac279..c6a58a8dc5a80 100644 --- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp +++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp @@ -418,8 +418,7 @@ Value Importer::processConstant(llvm::Constant *c) { } if (auto *GV = dyn_cast(c)) return bEntry.create(UnknownLoc::get(context), - processGlobal(GV), - ArrayRef()); + processGlobal(GV)); if (auto *ce = dyn_cast(c)) { llvm::Instruction *i = ce->getAsInstruction(); @@ -727,7 +726,7 @@ LogicalResult Importer::processInstruction(llvm::Instruction *inst) { if (!calledValue) return failure(); ops.insert(ops.begin(), calledValue); - op = b.create(loc, tys, ops, ArrayRef()); + op = b.create(loc, tys, ops); } if (!ci->getType()->isVoidTy()) v = op->getResult(0); @@ -809,7 +808,7 @@ LogicalResult Importer::processInstruction(llvm::Instruction *inst) { Type type = processType(inst->getType()); if (!type) return failure(); - v = b.create(loc, type, ops, ArrayRef()); + v = b.create(loc, type, ops); return success(); } } diff --git a/mlir/test/mlir-tblgen/op-decl.td b/mlir/test/mlir-tblgen/op-decl.td index b596eee038291..f8ff60e355574 100644 --- a/mlir/test/mlir-tblgen/op-decl.td +++ b/mlir/test/mlir-tblgen/op-decl.td @@ -171,6 +171,56 @@ def NS_GOp : NS_Op<"op_with_fixed_return_type", []> { // CHECK-LABEL: class GOp : // CHECK: static ::mlir::LogicalResult inferReturnTypes +// Check default value for collective params builder. Check that other builders +// are generated as well. +def NS_HCollectiveParamsOp : NS_Op<"op_collective_params", []> { + let arguments = (ins AnyType:$a); + let results = (outs AnyType:$b); +} + +// CHECK_LABEL: class NS_HCollectiveParamsOp : +// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::Type b, ::mlir::Value a); +// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> resultTypes, ::mlir::Value a); +// CHECK: static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}) + +// Check suppression of "separate arg, separate result" build method for an op +// with single variadic arg and single variadic result (since it will be +// ambiguous with the collective params build method). +def NS_HCollectiveParamsSuppress0Op : NS_Op<"op_collective_suppress0", []> { + let arguments = (ins Variadic:$a); + let results = (outs Variadic:$b); +} + +// CHECK_LABEL: class NS_HCollectiveParamsSuppress0Op : +// CHECK-NOT: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> b, ::mlir::ValueRange a); +// CHECK: static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); + +// Check suppression of "separate arg, collective result" build method for an op +// with single variadic arg and non variadic result (since it will be +// ambiguous with the collective params build method). +def NS_HCollectiveParamsSuppress1Op : NS_Op<"op_collective_suppress1", []> { + let arguments = (ins Variadic:$a); + let results = (outs I32:$b); +} + +// CHECK_LABEL: class NS_HCollectiveParamsSuppress1Op : +// CHECK-NOT: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> b, ::mlir::ValueRange a); +// CHECK: static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); + +// Check suppression of "separate arg, collective result" build method for an op +// with single variadic arg and > 1 variadic result (since it will be +// ambiguous with the collective params build method). Note that "separate arg, +// separate result" build method should be generated in this case as its not +// ambiguous with the collective params build method. +def NS_HCollectiveParamsSuppress2Op : NS_Op<"op_collective_suppress2", [SameVariadicResultSize]> { + let arguments = (ins Variadic:$a); + let results = (outs Variadic:$b, Variadic:$c); +} +// CHECK_LABEL: class NS_HCollectiveParamsSuppress2Op : +// CHECK: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> b, ::llvm::ArrayRef<::mlir::Type> c, ::mlir::ValueRange a); +// CHECK-NOT: static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> b, ::mlir::ValueRange a); +// CHECK: static void build(::mlir::OpBuilder &, ::mlir::OperationState &odsState, ::llvm::ArrayRef<::mlir::Type> resultTypes, ::mlir::ValueRange operands, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes = {}); + // Check that default builders can be suppressed. // --- diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp index b2b4245989b58..5e009e6025243 100644 --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -955,14 +955,51 @@ void OpEmitter::genSeparateArgParamBuilder() { llvm_unreachable("unhandled TypeParamKind"); }; + // A separate arg param builder method will have a signature which is + // ambiguous with the collective params build method (generated in + // `genCollectiveParamBuilder` function below) if it has a single + // `ArrayReg` parameter for result types and a single `ArrayRef` + // parameter for the operands, no parameters after that, and the collective + // params build method has `attributes` as its last parameter (with + // a default value). This will happen when all of the following are true: + // 1. [`attributes` as last parameter in collective params build method]: + // getNumVariadicRegions must be 0 (otherwise the collective params build + // method ends with a `numRegions` param, and we don't specify default + // value for attributes). + // 2. [single `ArrayRef` parameter for operands, and no parameters + // after that]: numArgs() must be 1 (if not, each arg gets a separate param + // in the build methods generated here) and the single arg must be a + // non-attribute variadic argument. + // 3. [single `ArrayReg` parameter for result types]: + // 3a. paramKind should be Collective, or + // 3b. paramKind should be Separate and there should be a single variadic + // result + // + // In that case, skip generating such ambiguous build methods here. + bool hasSingleVariadicResult = + op.getNumResults() == 1 && op.getResult(0).isVariadic(); + + bool hasSingleVariadicArg = + op.getNumArgs() == 1 && + op.getArg(0).is() && + op.getOperand(0).isVariadic(); + bool hasNoVariadicRegions = op.getNumVariadicRegions() == 0; + for (auto attrType : attrBuilderType) { - emit(attrType, TypeParamKind::Separate, /*inferType=*/false); + // Case 3b above. + if (!(hasNoVariadicRegions && hasSingleVariadicArg && + hasSingleVariadicResult)) + emit(attrType, TypeParamKind::Separate, /*inferType=*/false); if (canInferType(op)) emit(attrType, TypeParamKind::None, /*inferType=*/true); - // Emit separate arg build with collective type, unless there is only one - // variadic result, in which case the above would have already generated - // the same build method. - if (!(op.getNumResults() == 1 && op.getResult(0).isVariableLength())) + // The separate arg + collective param kind method will be: + // (a) Same as the separate arg + separate param kind method if there is + // only one variadic result. + // (b) Ambiguous with the collective params method under conditions in (3a) + // above. + // In either case, skip generating such build method. + if (!hasSingleVariadicResult && + !(hasNoVariadicRegions && hasSingleVariadicArg)) emit(attrType, TypeParamKind::Collective, /*inferType=*/false); } } @@ -1184,8 +1221,12 @@ void OpEmitter::genCollectiveParamBuilder() { ", ::llvm::ArrayRef<::mlir::Type> resultTypes, ::mlir::ValueRange " "operands, " "::llvm::ArrayRef<::mlir::NamedAttribute> attributes"; - if (op.getNumVariadicRegions()) + if (op.getNumVariadicRegions()) { params += ", unsigned numRegions"; + } else { + // Provide default value for `attributes` since its the last parameter + params += " = {}"; + } auto &m = opClass.newMethod("void", "build", params, OpMethod::MP_Static); auto &body = m.body(); From 32d35fb74b2672ddf3674188423b71837afea8c4 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Mon, 13 Jul 2020 13:44:01 -0700 Subject: [PATCH 153/771] [lldb] Remove unused argument (NFC) Nobody is writing to the stream so there's no point in passing it around. --- lldb/include/lldb/Target/Process.h | 4 ++-- lldb/source/API/SBTarget.cpp | 2 +- .../Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp | 6 +++--- lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp | 2 +- lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h | 3 +-- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 3 +-- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h | 2 +- lldb/source/Target/Platform.cpp | 2 +- lldb/source/Target/Process.cpp | 6 +++--- 9 files changed, 14 insertions(+), 16 deletions(-) diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index a3fb3447169e6..bf9b64547ed50 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -737,7 +737,7 @@ class Process : public std::enable_shared_from_this, /// /// \return /// Returns an error object. - virtual Status ConnectRemote(Stream *strm, llvm::StringRef remote_url); + virtual Status ConnectRemote(llvm::StringRef remote_url); bool GetShouldDetach() const { return m_should_detach; } @@ -925,7 +925,7 @@ class Process : public std::enable_shared_from_this, /// /// \return /// Returns an error object. - virtual Status DoConnectRemote(Stream *strm, llvm::StringRef remote_url) { + virtual Status DoConnectRemote(llvm::StringRef remote_url) { Status error; error.SetErrorString("remote connections are not supported"); return error; diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index ca75e91bd9069..b84e9f10fafe9 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -566,7 +566,7 @@ lldb::SBProcess SBTarget::ConnectRemote(SBListener &listener, const char *url, if (process_sp) { sb_process.SetSP(process_sp); - error.SetError(process_sp->ConnectRemote(nullptr, url)); + error.SetError(process_sp->ConnectRemote(url)); } else { error.SetErrorString("unable to create lldb_private::Process"); } diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 18631a0c53156..21bf7f4ac46d3 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -503,10 +503,10 @@ lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess( "gdb-remote", nullptr); if (process_sp) { - error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); + error = process_sp->ConnectRemote(connect_url.c_str()); // Retry the connect remote one time... if (error.Fail()) - error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); + error = process_sp->ConnectRemote(connect_url.c_str()); if (error.Success()) error = process_sp->Launch(launch_info); else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) { @@ -589,7 +589,7 @@ lldb::ProcessSP PlatformRemoteGDBServer::Attach( target->CreateProcess(attach_info.GetListenerForProcess(debugger), "gdb-remote", nullptr); if (process_sp) { - error = process_sp->ConnectRemote(nullptr, connect_url.c_str()); + error = process_sp->ConnectRemote(connect_url.c_str()); if (error.Success()) { ListenerSP listener_sp = attach_info.GetHijackListener(); if (listener_sp) diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 5b728a5f2960f..2f4a8917a78a7 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -217,7 +217,7 @@ bool ProcessKDP::GetHostArchitecture(ArchSpec &arch) { return false; } -Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) { +Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) { Status error; // Don't let any JIT happen when doing KDP as we can't allocate memory and we diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h index 67f8ac0698204..52af56134404c 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h @@ -67,8 +67,7 @@ class ProcessKDP : public lldb_private::Process { WillAttachToProcessWithName(const char *process_name, bool wait_for_launch) override; - lldb_private::Status DoConnectRemote(lldb_private::Stream *strm, - llvm::StringRef remote_url) override; + lldb_private::Status DoConnectRemote(llvm::StringRef remote_url) override; lldb_private::Status DoAttachToProcessWithID( lldb::pid_t pid, diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index ff263fa162587..1fed8e0642670 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -629,8 +629,7 @@ Status ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name, return WillLaunchOrAttach(); } -Status ProcessGDBRemote::DoConnectRemote(Stream *strm, - llvm::StringRef remote_url) { +Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); Status error(WillLaunchOrAttach()); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 22d86d6cdd75d..ba967727ae3b8 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -85,7 +85,7 @@ class ProcessGDBRemote : public Process, Status WillAttachToProcessWithName(const char *process_name, bool wait_for_launch) override; - Status DoConnectRemote(Stream *strm, llvm::StringRef remote_url) override; + Status DoConnectRemote(llvm::StringRef remote_url) override; Status WillLaunchOrAttach(); diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 8d4bea2148147..95c35ea826a07 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -1806,7 +1806,7 @@ lldb::ProcessSP Platform::ConnectProcess(llvm::StringRef connect_url, if (!process_sp) return nullptr; - error = process_sp->ConnectRemote(&debugger.GetOutputStream(), connect_url); + error = process_sp->ConnectRemote(connect_url); if (error.Fail()) return nullptr; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 78f75981a94dd..d777a27139119 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1270,7 +1270,7 @@ void Process::UpdateThreadListIfNeeded() { for (size_t i = 0; i < num_old_threads; ++i) old_thread_list.GetThreadAtIndex(i, false)->ClearBackingThread(); // See if the OS plugin reports all threads. If it does, then - // it is safe to clear unseen thread's plans here. Otherwise we + // it is safe to clear unseen thread's plans here. Otherwise we // should preserve them in case they show up again: clear_unused_threads = GetOSPluginReportsAllThreads(); @@ -3096,14 +3096,14 @@ void Process::CompleteAttach() { } } -Status Process::ConnectRemote(Stream *strm, llvm::StringRef remote_url) { +Status Process::ConnectRemote(llvm::StringRef remote_url) { m_abi_sp.reset(); m_process_input_reader.reset(); // Find the process and its architecture. Make sure it matches the // architecture of the current Target, and if not adjust it. - Status error(DoConnectRemote(strm, remote_url)); + Status error(DoConnectRemote(remote_url)); if (error.Success()) { if (GetID() != LLDB_INVALID_PROCESS_ID) { EventSP event_sp; From 77c9aafc5d85a816c20d1f1fb176024bc0b8d0fe Mon Sep 17 00:00:00 2001 From: Walter Erquinigo Date: Mon, 13 Jul 2020 12:10:49 -0700 Subject: [PATCH 154/771] Retry ""[lldb-vscode] Fix TestVSCode_module"" Original commit c60216db15132401ff60c08ccef899321f63b6b6. The test can only run on Darwin because of how it was setup, so I'm enforcing that. Summary: Test Plan: Reviewers: Subscribers: Tasks: Tags: --- .../test/tools/lldb-vscode/vscode.py | 23 +++++ .../API/tools/lldb-vscode/module/Makefile | 13 +++ .../lldb-vscode/module/TestVSCode_module.py | 72 +++++++++++++++ .../test/API/tools/lldb-vscode/module/foo.cpp | 3 + lldb/test/API/tools/lldb-vscode/module/foo.h | 1 + .../API/tools/lldb-vscode/module/main.cpp | 6 ++ lldb/tools/lldb-vscode/JSONUtils.cpp | 44 +++++++++ lldb/tools/lldb-vscode/JSONUtils.h | 13 +++ lldb/tools/lldb-vscode/VSCode.cpp | 5 + lldb/tools/lldb-vscode/lldb-vscode.cpp | 92 +++++++++++++++++++ 10 files changed, 272 insertions(+) create mode 100644 lldb/test/API/tools/lldb-vscode/module/Makefile create mode 100644 lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py create mode 100644 lldb/test/API/tools/lldb-vscode/module/foo.cpp create mode 100644 lldb/test/API/tools/lldb-vscode/module/foo.h create mode 100644 lldb/test/API/tools/lldb-vscode/module/main.cpp diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py index 1ad168e794cff..6b1c1c961b545 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py @@ -113,6 +113,7 @@ def __init__(self, recv, send, init_commands): self.initialize_body = None self.thread_stop_reasons = {} self.breakpoint_events = [] + self.module_events = {} self.sequence = 1 self.threads = None self.recv_thread.start() @@ -133,6 +134,9 @@ def validate_response(cls, command, response): if command['seq'] != response['request_seq']: raise ValueError('seq mismatch in response') + def get_active_modules(self): + return self.module_events + def get_output(self, category, timeout=0.0, clear=True): self.output_condition.acquire() output = None @@ -218,6 +222,15 @@ def handle_recv_packet(self, packet): self.breakpoint_events.append(packet) # no need to add 'breakpoint' event packets to our packets list return keepGoing + elif event == 'module': + reason = body['reason'] + if (reason == 'new' or reason == 'changed'): + self.module_events[body['module']['name']] = body['module'] + elif reason == 'removed': + if body['module']['name'] in self.module_events: + self.module_events.pop(body['module']['name']) + return keepGoing + elif packet_type == 'response': if packet['command'] == 'disconnect': keepGoing = False @@ -747,6 +760,16 @@ def request_setFunctionBreakpoints(self, names, condition=None, } return self.send_recv(command_dict) + def request_getCompileUnits(self, moduleId): + args_dict = {'moduleId': moduleId} + command_dict = { + 'command': 'getCompileUnits', + 'type': 'request', + 'arguments': args_dict + } + response = self.send_recv(command_dict) + return response + def request_completions(self, text): args_dict = { 'text': text, diff --git a/lldb/test/API/tools/lldb-vscode/module/Makefile b/lldb/test/API/tools/lldb-vscode/module/Makefile new file mode 100644 index 0000000000000..1fb944b138937 --- /dev/null +++ b/lldb/test/API/tools/lldb-vscode/module/Makefile @@ -0,0 +1,13 @@ +DYLIB_NAME := foo +DYLIB_CXX_SOURCES := foo.cpp +CXX_SOURCES := main.cpp + +all: a.out.stripped + +include Makefile.rules + +a.out.stripped: a.out.dSYM + strip -o a.out.stripped a.out +ifneq "$(CODESIGN)" "" + $(CODESIGN) -fs - a.out.stripped +endif diff --git a/lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py b/lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py new file mode 100644 index 0000000000000..461ac201a73f4 --- /dev/null +++ b/lldb/test/API/tools/lldb-vscode/module/TestVSCode_module.py @@ -0,0 +1,72 @@ +""" +Test lldb-vscode setBreakpoints request +""" + +from __future__ import print_function + +import unittest2 +import vscode +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import lldbvscode_testcase + + +class TestVSCode_module(lldbvscode_testcase.VSCodeTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + + @skipIfWindows + @skipUnlessDarwin + @skipIfRemote + def test_modules_event(self): + program_basename = "a.out.stripped" + program= self.getBuildArtifact(program_basename) + self.build_and_launch(program) + functions = ['foo'] + breakpoint_ids = self.set_function_breakpoints(functions) + self.assertEquals(len(breakpoint_ids), len(functions), + 'expect one breakpoint') + self.continue_to_breakpoints(breakpoint_ids) + active_modules = self.vscode.get_active_modules() + self.assertIn(program_basename, active_modules, '%s module is in active modules' % (program_basename)) + program_module = active_modules[program_basename] + self.assertIn('name', program_module, 'make sure name is in module') + self.assertEqual(program_basename, program_module['name']) + self.assertIn('path', program_module, 'make sure path is in module') + self.assertEqual(program, program_module['path']) + self.assertTrue('symbolFilePath' not in program_module, 'Make sure a.out.stripped has no debug info') + self.assertEqual('Symbols not found.', program_module['symbolStatus']) + symbol_path = self.getBuildArtifact("a.out") + self.vscode.request_evaluate('`%s' % ('target symbols add -s "%s" "%s"' % (program, symbol_path))) + active_modules = self.vscode.get_active_modules() + program_module = active_modules[program_basename] + self.assertEqual(program_basename, program_module['name']) + self.assertEqual(program, program_module['path']) + self.assertEqual('Symbols loaded.', program_module['symbolStatus']) + self.assertIn('symbolFilePath', program_module) + self.assertEqual(symbol_path, program_module['symbolFilePath']) + self.assertIn('addressRange', program_module) + + @skipIfWindows + @skipUnlessDarwin + @skipIfRemote + def test_compile_units(self): + program= self.getBuildArtifact("a.out") + self.build_and_launch(program) + source = "main.cpp" + main_source_path = self.getSourcePath(source) + breakpoint1_line = line_number(source, '// breakpoint 1') + lines = [breakpoint1_line] + breakpoint_ids = self.set_source_breakpoints(source, lines) + self.continue_to_breakpoints(breakpoint_ids) + moduleId = self.vscode.get_active_modules()['a.out']['id'] + response = self.vscode.request_getCompileUnits(moduleId) + print(response['body']) + self.assertTrue(response['body']) + self.assertTrue(len(response['body']['compileUnits']) == 1, + 'Only one source file should exist') + self.assertTrue(response['body']['compileUnits'][0]['compileUnitPath'] == main_source_path, + 'Real path to main.cpp matches') + diff --git a/lldb/test/API/tools/lldb-vscode/module/foo.cpp b/lldb/test/API/tools/lldb-vscode/module/foo.cpp new file mode 100644 index 0000000000000..9dba85a9cccab --- /dev/null +++ b/lldb/test/API/tools/lldb-vscode/module/foo.cpp @@ -0,0 +1,3 @@ +int foo() { + return 12; +} diff --git a/lldb/test/API/tools/lldb-vscode/module/foo.h b/lldb/test/API/tools/lldb-vscode/module/foo.h new file mode 100644 index 0000000000000..5d5f8f0c9e786 --- /dev/null +++ b/lldb/test/API/tools/lldb-vscode/module/foo.h @@ -0,0 +1 @@ +int foo(); diff --git a/lldb/test/API/tools/lldb-vscode/module/main.cpp b/lldb/test/API/tools/lldb-vscode/module/main.cpp new file mode 100644 index 0000000000000..4ff2b2360eb97 --- /dev/null +++ b/lldb/test/API/tools/lldb-vscode/module/main.cpp @@ -0,0 +1,6 @@ +#include "foo.h" + +int main(int argc, char const *argv[]) { + foo(); + return 0; // breakpoint 1 +} diff --git a/lldb/tools/lldb-vscode/JSONUtils.cpp b/lldb/tools/lldb-vscode/JSONUtils.cpp index 8fcf179b29aad..86c29fb238112 100644 --- a/lldb/tools/lldb-vscode/JSONUtils.cpp +++ b/lldb/tools/lldb-vscode/JSONUtils.cpp @@ -327,6 +327,41 @@ llvm::json::Value CreateBreakpoint(lldb::SBBreakpoint &bp, return llvm::json::Value(std::move(object)); } +llvm::json::Value CreateModule(lldb::SBModule &module) { + llvm::json::Object object; + if (!module.IsValid()) + return llvm::json::Value(std::move(object)); + object.try_emplace("id", std::string(module.GetUUIDString())); + object.try_emplace("name", std::string(module.GetFileSpec().GetFilename())); + char module_path_arr[PATH_MAX]; + module.GetFileSpec().GetPath(module_path_arr, sizeof(module_path_arr)); + std::string module_path(module_path_arr); + object.try_emplace("path", module_path); + if (module.GetNumCompileUnits() > 0) { + object.try_emplace("symbolStatus", "Symbols loaded."); + char symbol_path_arr[PATH_MAX]; + module.GetSymbolFileSpec().GetPath(symbol_path_arr, sizeof(symbol_path_arr)); + std::string symbol_path(symbol_path_arr); + object.try_emplace("symbolFilePath", symbol_path); + } else { + object.try_emplace("symbolStatus", "Symbols not found."); + } + std::string loaded_addr = std::to_string( + module.GetObjectFileHeaderAddress().GetLoadAddress(g_vsc.target)); + object.try_emplace("addressRange", loaded_addr); + std::string version_str; + uint32_t version_nums[3]; + uint32_t num_versions = module.GetVersion(version_nums, sizeof(version_nums)/sizeof(uint32_t)); + for (uint32_t i=0; i request_path, llvm::Optional request_line) { @@ -902,4 +937,13 @@ llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference, return llvm::json::Value(std::move(object)); } +llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit) { + llvm::json::Object object; + char unit_path_arr[PATH_MAX]; + unit.GetFileSpec().GetPath(unit_path_arr, sizeof(unit_path_arr)); + std::string unit_path(unit_path_arr); + object.try_emplace("compileUnitPath", unit_path); + return llvm::json::Value(std::move(object)); +} + } // namespace lldb_vscode diff --git a/lldb/tools/lldb-vscode/JSONUtils.h b/lldb/tools/lldb-vscode/JSONUtils.h index af76683d11cc8..e2ccfdb1fb2b6 100644 --- a/lldb/tools/lldb-vscode/JSONUtils.h +++ b/lldb/tools/lldb-vscode/JSONUtils.h @@ -13,6 +13,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/JSON.h" #include "VSCodeForward.h" +#include "lldb/API/SBModule.h" namespace lldb_vscode { @@ -237,6 +238,16 @@ CreateBreakpoint(lldb::SBBreakpoint &bp, llvm::Optional request_path = llvm::None, llvm::Optional request_line = llvm::None); +/// Converts a LLDB module to a VS Code DAP module for use in "modules" events. +/// +/// \param[in] module +/// A LLDB module object to convert into a JSON value +/// +/// \return +/// A "Module" JSON object with that follows the formal JSON +/// definition outlined by Microsoft. +llvm::json::Value CreateModule(lldb::SBModule &module); + /// Create a "Event" JSON object using \a event_name as the event name /// /// \param[in] event_name @@ -430,6 +441,8 @@ llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, uint32_t stop_id); llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference, int64_t varID, bool format_hex); +llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit unit); + } // namespace lldb_vscode #endif diff --git a/lldb/tools/lldb-vscode/VSCode.cpp b/lldb/tools/lldb-vscode/VSCode.cpp index b2d16f96d1f2b..4a30aef3a6db4 100644 --- a/lldb/tools/lldb-vscode/VSCode.cpp +++ b/lldb/tools/lldb-vscode/VSCode.cpp @@ -358,6 +358,11 @@ void VSCode::SetTarget(const lldb::SBTarget target) { lldb::SBTarget::eBroadcastBitBreakpointChanged); listener.StartListeningForEvents(this->broadcaster, eBroadcastBitStopEventThread); + listener.StartListeningForEvents( + this->target.GetBroadcaster(), + lldb::SBTarget::eBroadcastBitModulesLoaded | + lldb::SBTarget::eBroadcastBitModulesUnloaded | + lldb::SBTarget::eBroadcastBitSymbolsLoaded); } } diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp index 168873f827527..27ee832677d72 100644 --- a/lldb/tools/lldb-vscode/lldb-vscode.cpp +++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include "llvm/ADT/ArrayRef.h" #include "llvm/Option/Arg.h" @@ -434,6 +435,30 @@ void EventThreadFunction() { g_vsc.SendJSON(llvm::json::Value(std::move(bp_event))); } } + } else if (lldb::SBTarget::EventIsTargetEvent(event)) { + if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded || + event_mask & lldb::SBTarget::eBroadcastBitModulesUnloaded || + event_mask & lldb::SBTarget::eBroadcastBitSymbolsLoaded) { + int num_modules = lldb::SBTarget::GetNumModulesFromEvent(event); + for (int i = 0; i < num_modules; i++) { + auto module = lldb::SBTarget::GetModuleAtIndexFromEvent(i, event); + auto module_event = CreateEventObject("module"); + llvm::json::Value module_value = CreateModule(module); + llvm::json::Object body; + if (event_mask & lldb::SBTarget::eBroadcastBitModulesLoaded) { + body.try_emplace("reason", "new"); + } else if (event_mask & + lldb::SBTarget::eBroadcastBitModulesUnloaded) { + body.try_emplace("reason", "removed"); + } else if (event_mask & + lldb::SBTarget::eBroadcastBitSymbolsLoaded) { + body.try_emplace("reason", "changed"); + } + body.try_emplace("module", module_value); + module_event.try_emplace("body", std::move(body)); + g_vsc.SendJSON(llvm::json::Value(std::move(module_event))); + } + } } else if (event.BroadcasterMatchesRef(g_vsc.broadcaster)) { if (event_mask & eBroadcastBitStopEventThread) { done = true; @@ -1149,6 +1174,72 @@ void request_evaluate(const llvm::json::Object &request) { g_vsc.SendJSON(llvm::json::Value(std::move(response))); } +// "getCompileUnitsRequest": { +// "allOf": [ { "$ref": "#/definitions/Request" }, { +// "type": "object", +// "description": "Compile Unit request; value of command field is +// 'getCompileUnits'.", +// "properties": { +// "command": { +// "type": "string", +// "enum": [ "getCompileUnits" ] +// }, +// "arguments": { +// "$ref": "#/definitions/getCompileUnitRequestArguments" +// } +// }, +// "required": [ "command", "arguments" ] +// }] +// }, +// "getCompileUnitsRequestArguments": { +// "type": "object", +// "description": "Arguments for 'getCompileUnits' request.", +// "properties": { +// "moduleId": { +// "type": "string", +// "description": "The ID of the module." +// } +// }, +// "required": [ "moduleId" ] +// }, +// "getCompileUnitsResponse": { +// "allOf": [ { "$ref": "#/definitions/Response" }, { +// "type": "object", +// "description": "Response to 'getCompileUnits' request.", +// "properties": { +// "body": { +// "description": "Response to 'getCompileUnits' request. Array of +// paths of compile units." +// } +// } +// }] +// } + +void request_getCompileUnits(const llvm::json::Object &request) { + llvm::json::Object response; + FillResponse(request, response); + lldb::SBProcess process = g_vsc.target.GetProcess(); + llvm::json::Object body; + llvm::json::Array units; + auto arguments = request.getObject("arguments"); + std::string module_id = std::string(GetString(arguments, "moduleId")); + int num_modules = g_vsc.target.GetNumModules(); + for (int i = 0; i < num_modules; i++) { + auto curr_module = g_vsc.target.GetModuleAtIndex(i); + if (module_id == curr_module.GetUUIDString()) { + int num_units = curr_module.GetNumCompileUnits(); + for (int j = 0; j < num_units; j++) { + auto curr_unit = curr_module.GetCompileUnitAtIndex(j);\ + units.emplace_back(CreateCompileUnit(curr_unit));\ + } + body.try_emplace("compileUnits", std::move(units)); + break; + } + } + response.try_emplace("body", std::move(body)); + g_vsc.SendJSON(llvm::json::Value(std::move(response))); +} + // "InitializeRequest": { // "allOf": [ { "$ref": "#/definitions/Request" }, { // "type": "object", @@ -2734,6 +2825,7 @@ const std::map &GetRequestHandlers() { REQUEST_CALLBACK(disconnect), REQUEST_CALLBACK(evaluate), REQUEST_CALLBACK(exceptionInfo), + REQUEST_CALLBACK(getCompileUnits), REQUEST_CALLBACK(initialize), REQUEST_CALLBACK(launch), REQUEST_CALLBACK(next), From b9c2dd11a5139b754afca050effac80f3b638bc8 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 19 Jun 2020 20:25:33 +0200 Subject: [PATCH 155/771] [ADT] Specialize std::swap() for SetVector This is intended to address a compile-time regression from 1eddce4177cfddc86d4696b758904443b0b4f193. A SmallPtrSet was replaced with a SetVector there, which had an unexpected large compile-time impact. It turns out that this structure is getting swapped a lot, and previously this used an optimized std::swap() specialization for SmallPtrSet. Now it ends up using the default, triple-move based implementation, which is much more expensive. This patch (partly) addresses the issue by specializing std::swap() for SetVector. Differential Revision: https://reviews.llvm.org/D82230 --- llvm/include/llvm/ADT/SetVector.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/llvm/include/llvm/ADT/SetVector.h b/llvm/include/llvm/ADT/SetVector.h index 901d5b1bcd90f..91ad72143ed35 100644 --- a/llvm/include/llvm/ADT/SetVector.h +++ b/llvm/include/llvm/ADT/SetVector.h @@ -263,6 +263,11 @@ class SetVector { remove(*SI); } + void swap(SetVector &RHS) { + set_.swap(RHS.set_); + vector_.swap(RHS.vector_); + } + private: /// A wrapper predicate designed for use with std::remove_if. /// @@ -308,4 +313,22 @@ class SmallSetVector } // end namespace llvm +namespace std { + +/// Implement std::swap in terms of SetVector swap. +template +inline void +swap(llvm::SetVector &LHS, llvm::SetVector &RHS) { + LHS.swap(RHS); +} + +/// Implement std::swap in terms of SmallSetVector swap. +template +inline void +swap(llvm::SmallSetVector &LHS, llvm::SmallSetVector &RHS) { + LHS.swap(RHS); +} + +} // end namespace std + #endif // LLVM_ADT_SETVECTOR_H From affbc0cd1cc87826c2636f8903d85c911aef75ff Mon Sep 17 00:00:00 2001 From: Nicolas Vasilache Date: Mon, 13 Jul 2020 11:04:09 -0400 Subject: [PATCH 156/771] [mlir] Add alignment attribute to LLVM memory ops and use in vector.transfer Summary: The native alignment may generally not be used when lowering a vector.transfer to the underlying load/store operation. This revision fixes the unmasked load/store alignment to match that of the masked path. Differential Revision: https://reviews.llvm.org/D83684 --- mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 88 ++++++++++++++----- .../Vector/CPU/test-transfer-read.mlir | 13 +++ .../Vector/CPU/test-transfer-write.mlir | 16 ++-- .../VectorToLLVM/ConvertVectorToLLVM.cpp | 11 ++- .../VectorToLLVM/vector-to-llvm.mlir | 2 +- 5 files changed, 97 insertions(+), 33 deletions(-) diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index 663a820905ce3..ce0b3de82d2c9 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -215,19 +215,36 @@ def LLVM_FDivOp : LLVM_ArithmeticOp<"fdiv", "CreateFDiv">; def LLVM_FRemOp : LLVM_ArithmeticOp<"frem", "CreateFRem">; def LLVM_FNegOp : LLVM_UnaryArithmeticOp<"fneg", "CreateFNeg">; +// Common code definition that is used to verify and set the alignment attribute +// of LLVM ops that accept such an attribute. +class MemoryOpWithAlignmentBase { + code alignmentVerifierCode = [{ + if (alignment().hasValue()) { + auto align = alignment().getValue().getSExtValue(); + if (align < 0) + return emitOpError("expected positive alignment"); + } + return success(); + }]; + code setAlignmentCode = [{ + if ($alignment.hasValue()) { + auto align = $alignment.getValue().getZExtValue(); + if (align != 0) + inst->setAlignment(llvm::Align(align)); + } + }]; +} + // Memory-related operations. def LLVM_AllocaOp : + MemoryOpWithAlignmentBase, LLVM_OneResultOp<"alloca">, Arguments<(ins LLVM_Type:$arraySize, OptionalAttr:$alignment)> { string llvmBuilder = [{ - auto *alloca = builder.CreateAlloca( + auto *inst = builder.CreateAlloca( $_resultType->getPointerElementType(), $arraySize); - if ($alignment.hasValue()) { - auto align = $alignment.getValue().getZExtValue(); - if (align != 0) - alloca->setAlignment(llvm::Align(align)); - } - $res = alloca; + }] # setAlignmentCode # [{ + $res = inst; }]; let builders = [OpBuilder< "OpBuilder &b, OperationState &result, Type resultType, Value arraySize, " @@ -239,14 +256,7 @@ def LLVM_AllocaOp : }]>]; let parser = [{ return parseAllocaOp(parser, result); }]; let printer = [{ printAllocaOp(p, *this); }]; - let verifier = [{ - if (alignment().hasValue()) { - auto align = alignment().getValue().getSExtValue(); - if (align < 0) - return emitOpError("expected positive alignment"); - } - return success(); - }]; + let verifier = alignmentVerifierCode; } def LLVM_GEPOp : LLVM_OneResultOp<"getelementptr", [NoSideEffect]>, Arguments<(ins LLVM_Type:$base, Variadic:$indices)>, @@ -255,22 +265,56 @@ def LLVM_GEPOp : LLVM_OneResultOp<"getelementptr", [NoSideEffect]>, $base `[` $indices `]` attr-dict `:` functional-type(operands, results) }]; } -def LLVM_LoadOp : LLVM_OneResultOp<"load">, Arguments<(ins LLVM_Type:$addr)>, - LLVM_Builder<"$res = builder.CreateLoad($addr);"> { +def LLVM_LoadOp : + MemoryOpWithAlignmentBase, + LLVM_OneResultOp<"load">, + Arguments<(ins LLVM_Type:$addr, OptionalAttr:$alignment)> { + string llvmBuilder = [{ + auto *inst = builder.CreateLoad($addr); + }] # setAlignmentCode # [{ + $res = inst; + }]; let builders = [OpBuilder< - "OpBuilder &b, OperationState &result, Value addr", + "OpBuilder &b, OperationState &result, Value addr, unsigned alignment = 0", [{ auto type = addr.getType().cast().getPointerElementTy(); - build(b, result, type, addr); + build(b, result, type, addr, alignment); + }]>, + OpBuilder< + "OpBuilder &b, OperationState &result, Type t, Value addr, " + "unsigned alignment = 0", + [{ + if (alignment == 0) + return build(b, result, t, addr, IntegerAttr()); + build(b, result, t, addr, b.getI64IntegerAttr(alignment)); }]>]; let parser = [{ return parseLoadOp(parser, result); }]; let printer = [{ printLoadOp(p, *this); }]; + let verifier = alignmentVerifierCode; } -def LLVM_StoreOp : LLVM_ZeroResultOp<"store">, - Arguments<(ins LLVM_Type:$value, LLVM_Type:$addr)>, - LLVM_Builder<"builder.CreateStore($value, $addr);"> { +def LLVM_StoreOp : + MemoryOpWithAlignmentBase, + LLVM_ZeroResultOp<"store">, + Arguments<(ins LLVM_Type:$value, + LLVM_Type:$addr, + OptionalAttr:$alignment)> { + string llvmBuilder = [{ + auto *inst = builder.CreateStore($value, $addr); + }] # setAlignmentCode; + let builders = [ + OpBuilder< + "OpBuilder &b, OperationState &result, Value value, Value addr, " + "unsigned alignment = 0", + [{ + if (alignment == 0) + return build(b, result, ArrayRef{}, value, addr, IntegerAttr()); + build(b, result, ArrayRef{}, value, addr, + b.getI64IntegerAttr(alignment)); + }] + >]; let parser = [{ return parseStoreOp(parser, result); }]; let printer = [{ printStoreOp(p, *this); }]; + let verifier = alignmentVerifierCode; } // Casts. diff --git a/mlir/integration_test/Dialect/Vector/CPU/test-transfer-read.mlir b/mlir/integration_test/Dialect/Vector/CPU/test-transfer-read.mlir index f8934f06c0fd7..e6fa0df1ed7e3 100644 --- a/mlir/integration_test/Dialect/Vector/CPU/test-transfer-read.mlir +++ b/mlir/integration_test/Dialect/Vector/CPU/test-transfer-read.mlir @@ -12,6 +12,15 @@ func @transfer_read_1d(%A : memref, %base: index) { return } +func @transfer_read_unmasked_4(%A : memref, %base: index) { + %fm42 = constant -42.0: f32 + %f = vector.transfer_read %A[%base], %fm42 + {permutation_map = affine_map<(d0) -> (d0)>, masked = [false]} : + memref, vector<4xf32> + vector.print %f: vector<4xf32> + return +} + func @transfer_write_1d(%A : memref, %base: index) { %f0 = constant 0.0 : f32 %vf0 = splat %f0 : vector<4xf32> @@ -44,8 +53,12 @@ func @entry() { // Read shifted by 0 and pad with -42: // ( 0, 1, 2, 0, 0, -42, ..., -42) call @transfer_read_1d(%A, %c0) : (memref, index) -> () + // Read unmasked 4 @ 1, guaranteed to not overflow. + // Exercises proper alignment. + call @transfer_read_unmasked_4(%A, %c1) : (memref, index) -> () return } // CHECK: ( 2, 3, 4, -42, -42, -42, -42, -42, -42, -42, -42, -42, -42 ) // CHECK: ( 0, 1, 2, 0, 0, -42, -42, -42, -42, -42, -42, -42, -42 ) +// CHECK: ( 1, 2, 0, 0 ) diff --git a/mlir/integration_test/Dialect/Vector/CPU/test-transfer-write.mlir b/mlir/integration_test/Dialect/Vector/CPU/test-transfer-write.mlir index 57163700fc998..c61a1629dcfb0 100644 --- a/mlir/integration_test/Dialect/Vector/CPU/test-transfer-write.mlir +++ b/mlir/integration_test/Dialect/Vector/CPU/test-transfer-write.mlir @@ -3,11 +3,11 @@ // RUN: -shared-libs=%mlir_integration_test_dir/libmlir_c_runner_utils%shlibext | \ // RUN: FileCheck %s -func @transfer_write16_1d(%A : memref, %base: index) { +func @transfer_write16_unmasked_1d(%A : memref, %base: index) { %f = constant 16.0 : f32 %v = splat %f : vector<16xf32> vector.transfer_write %v, %A[%base] - {permutation_map = affine_map<(d0) -> (d0)>} + {permutation_map = affine_map<(d0) -> (d0)>, masked = [false]} : vector<16xf32>, memref return } @@ -53,14 +53,14 @@ func @entry() { %0 = call @transfer_read_1d(%A) : (memref) -> (vector<32xf32>) vector.print %0 : vector<32xf32> - // Overwrite with 16 values of 16 at base 4. - %c4 = constant 4: index - call @transfer_write16_1d(%A, %c4) : (memref, index) -> () + // Overwrite with 16 values of 16 at base 3. + // Statically guaranteed to be unmasked. Exercises proper alignment. + %c3 = constant 3: index + call @transfer_write16_unmasked_1d(%A, %c3) : (memref, index) -> () %1 = call @transfer_read_1d(%A) : (memref) -> (vector<32xf32>) vector.print %1 : vector<32xf32> // Overwrite with 13 values of 13 at base 3. - %c3 = constant 3: index call @transfer_write13_1d(%A, %c3) : (memref, index) -> () %2 = call @transfer_read_1d(%A) : (memref) -> (vector<32xf32>) vector.print %2 : vector<32xf32> @@ -93,8 +93,8 @@ func @entry() { } // CHECK: ( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) -// CHECK: ( 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) -// CHECK: ( 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) +// CHECK: ( 0, 0, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) +// CHECK: ( 0, 0, 0, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 16, 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) // CHECK: ( 0, 0, 0, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) // CHECK: ( 0, 0, 0, 17, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ) // CHECK: ( 0, 0, 0, 17, 17, 17, 17, 17, 13, 13, 13, 13, 13, 13, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0 ) diff --git a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp index 2be2bd9bb7d02..a59f02681c54e 100644 --- a/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp +++ b/mlir/lib/Conversion/VectorToLLVM/ConvertVectorToLLVM.cpp @@ -143,7 +143,10 @@ replaceTransferOpWithLoadOrStore(ConversionPatternRewriter &rewriter, LLVMTypeConverter &typeConverter, Location loc, TransferReadOp xferOp, ArrayRef operands, Value dataPtr) { - rewriter.replaceOpWithNewOp(xferOp, dataPtr); + unsigned align; + if (failed(getVectorTransferAlignment(typeConverter, xferOp, align))) + return failure(); + rewriter.replaceOpWithNewOp(xferOp, dataPtr, align); return success(); } @@ -176,8 +179,12 @@ replaceTransferOpWithLoadOrStore(ConversionPatternRewriter &rewriter, LLVMTypeConverter &typeConverter, Location loc, TransferWriteOp xferOp, ArrayRef operands, Value dataPtr) { + unsigned align; + if (failed(getVectorTransferAlignment(typeConverter, xferOp, align))) + return failure(); auto adaptor = TransferWriteOpAdaptor(operands); - rewriter.replaceOpWithNewOp(xferOp, adaptor.vector(), dataPtr); + rewriter.replaceOpWithNewOp(xferOp, adaptor.vector(), dataPtr, + align); return success(); } diff --git a/mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir b/mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir index 829edf5f66f17..874cb5cca1410 100644 --- a/mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir +++ b/mlir/test/Conversion/VectorToLLVM/vector-to-llvm.mlir @@ -935,7 +935,7 @@ func @transfer_read_1d_not_masked(%A : memref, %base: index) -> vector<17 // CHECK-SAME: !llvm<"float*"> to !llvm<"<17 x float>*"> // // 2. Rewrite as a load. -// CHECK: %[[loaded:.*]] = llvm.load %[[vecPtr]] : !llvm<"<17 x float>*"> +// CHECK: %[[loaded:.*]] = llvm.load %[[vecPtr]] {alignment = 4 : i64} : !llvm<"<17 x float>*"> func @genbool_1d() -> vector<8xi1> { %0 = vector.constant_mask [4] : vector<8xi1> From 427bda4e9b370d8efa96a7dbf503cdcb45616802 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Mon, 13 Jul 2020 14:37:21 -0700 Subject: [PATCH 157/771] [MC/AsmParser] layout-interdependency.s depends on having a proper triple Fix the requirements for that test. NFC --- llvm/test/MC/AsmParser/layout-interdependency.s | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/test/MC/AsmParser/layout-interdependency.s b/llvm/test/MC/AsmParser/layout-interdependency.s index 6e275e00d9ec7..6310610a718c1 100644 --- a/llvm/test/MC/AsmParser/layout-interdependency.s +++ b/llvm/test/MC/AsmParser/layout-interdependency.s @@ -1,4 +1,5 @@ # RUN: not llvm-mc --filetype=obj %s -o /dev/null 2>&1 | FileCheck %s +# REQUIRES: defaut_triple fct_end: From e51c7fb842ee61e8002634ad2e8548d748cb6172 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Mon, 13 Jul 2020 14:38:31 -0700 Subject: [PATCH 158/771] [debugify] Add targeted test for 2fa656c, NFC https://reviews.llvm.org/D78411 introduced test changes which relied on the ability to strip debugify metadata even if module-level metadata is missing. This introduces a more targeted test for that ability. --- .../CodeGen/Generic/MIRStripDebug/no-metadata-present.mir | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 llvm/test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir diff --git a/llvm/test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir b/llvm/test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir new file mode 100644 index 0000000000000..8952003384931 --- /dev/null +++ b/llvm/test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir @@ -0,0 +1,7 @@ +# RUN: llc -run-pass=mir-strip-debug -mir-strip-debugify-only=0 -o /dev/null %s + +--- +name: test +body: | + bb.1: +... From 724afa5a331372ff1684f2bffa6976887490cbaf Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Mon, 13 Jul 2020 23:50:00 +0200 Subject: [PATCH 159/771] [analyzer] Inline StringSet that's defined in a header That's just asking for ODR violations. Also drop a call to lower() that's not needed. --- clang/lib/StaticAnalyzer/Checkers/SmartPtr.h | 7 ------- clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h b/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h index 89b8965e4c9ad..ec43a23e30a9e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtr.h @@ -20,13 +20,6 @@ namespace clang { namespace ento { namespace smartptr { -/// Set of STL smart pointer class which we are trying to model. -const llvm::StringSet<> StdSmartPtrs = { - "shared_ptr", - "unique_ptr", - "weak_ptr", -}; - /// Returns true if the event call is on smart pointer. bool isStdSmartPtrCall(const CallEvent &Call); diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp index 91f2890788141..bcc7d4103c1c6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp @@ -73,7 +73,8 @@ bool isStdSmartPtrCall(const CallEvent &Call) { return false; if (RecordDecl->getDeclName().isIdentifier()) { - return smartptr::StdSmartPtrs.count(RecordDecl->getName().lower()); + StringRef Name = RecordDecl->getName(); + return Name == "shared_ptr" || Name == "unique_ptr" || Name == "weak_ptr"; } return false; } From 8c4a65b9b2ca6961139beca92de37eea479f00fa Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Fri, 13 Dec 2019 12:59:40 -0800 Subject: [PATCH 160/771] [ubsan] Check implicit casts in ObjC for-in statements Check that the implicit cast from `id` used to construct the element variable in an ObjC for-in statement is valid. This check is included as part of a new `objc-cast` sanitizer, outside of the main 'undefined' group, as (IIUC) the behavior it's checking for is not technically UB. The check can be extended to cover other kinds of invalid casts in ObjC. Partially addresses: rdar://12903059, rdar://9542496 Differential Revision: https://reviews.llvm.org/D71491 --- clang/docs/UndefinedBehaviorSanitizer.rst | 4 ++ clang/include/clang/Basic/Sanitizers.def | 2 + clang/lib/CodeGen/CGObjC.cpp | 34 +++++++++++++ clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/Driver/SanitizerArgs.cpp | 10 ++-- clang/lib/Driver/ToolChains/Darwin.cpp | 1 + clang/test/CodeGenObjC/for-in.m | 17 ++++++- compiler-rt/lib/ubsan/ubsan_checks.inc | 1 + compiler-rt/lib/ubsan/ubsan_handlers.cpp | 31 ++++++++++++ compiler-rt/lib/ubsan/ubsan_handlers.h | 8 ++++ compiler-rt/lib/ubsan/ubsan_value.cpp | 48 +++++++++++++++++++ compiler-rt/lib/ubsan/ubsan_value.h | 3 ++ .../ubsan_minimal/ubsan_minimal_handlers.cpp | 1 + .../test/ubsan/TestCases/Misc/objc-cast.m | 27 +++++++++++ 14 files changed, 183 insertions(+), 5 deletions(-) create mode 100644 compiler-rt/test/ubsan/TestCases/Misc/objc-cast.m diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst index 0a27810150db9..76676dfce95b4 100644 --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -127,6 +127,10 @@ Available checks are: is annotated with ``_Nonnull``. - ``-fsanitize=nullability-return``: Returning null from a function with a return type annotated with ``_Nonnull``. + - ``-fsanitize=objc-cast``: Invalid implicit cast of an ObjC object pointer + to an incompatible type. This is often unintentional, but is not undefined + behavior, therefore the check is not a part of the ``undefined`` group. + Currently only supported on Darwin. - ``-fsanitize=object-size``: An attempt to potentially use bytes which the optimizer can determine are not part of the object being accessed. This will also detect some types of undefined behavior that may not diff --git a/clang/include/clang/Basic/Sanitizers.def b/clang/include/clang/Basic/Sanitizers.def index 0037cc2146f26..2912bdd44b2db 100644 --- a/clang/include/clang/Basic/Sanitizers.def +++ b/clang/include/clang/Basic/Sanitizers.def @@ -156,6 +156,8 @@ SANITIZER_GROUP("implicit-integer-arithmetic-value-change", ImplicitIntegerArithmeticValueChange, ImplicitIntegerSignChange | ImplicitSignedIntegerTruncation) +SANITIZER("objc-cast", ObjCCast) + // FIXME: //SANITIZER_GROUP("implicit-integer-conversion", ImplicitIntegerConversion, // ImplicitIntegerArithmeticValueChange | diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 158a548e66c1e..cd2b84f5dd203 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1836,6 +1836,40 @@ void CodeGenFunction::EmitObjCForCollectionStmt(const ObjCForCollectionStmt &S){ llvm::Value *CurrentItem = Builder.CreateAlignedLoad(CurrentItemPtr, getPointerAlign()); + if (SanOpts.has(SanitizerKind::ObjCCast)) { + // Before using an item from the collection, check that the implicit cast + // from id to the element type is valid. This is done with instrumentation + // roughly corresponding to: + // + // if (![item isKindOfClass:expectedCls]) { /* emit diagnostic */ } + const ObjCObjectPointerType *ObjPtrTy = + elementType->getAsObjCInterfacePointerType(); + const ObjCInterfaceType *InterfaceTy = + ObjPtrTy ? ObjPtrTy->getInterfaceType() : nullptr; + if (InterfaceTy) { + SanitizerScope SanScope(this); + auto &C = CGM.getContext(); + assert(InterfaceTy->getDecl() && "No decl for ObjC interface type"); + Selector IsKindOfClassSel = GetUnarySelector("isKindOfClass", C); + CallArgList IsKindOfClassArgs; + llvm::Value *Cls = + CGM.getObjCRuntime().GetClass(*this, InterfaceTy->getDecl()); + IsKindOfClassArgs.add(RValue::get(Cls), C.getObjCClassType()); + llvm::Value *IsClass = + CGM.getObjCRuntime() + .GenerateMessageSend(*this, ReturnValueSlot(), C.BoolTy, + IsKindOfClassSel, CurrentItem, + IsKindOfClassArgs) + .getScalarVal(); + llvm::Constant *StaticData[] = { + EmitCheckSourceLocation(S.getBeginLoc()), + EmitCheckTypeDescriptor(QualType(InterfaceTy, 0))}; + EmitCheck({{IsClass, SanitizerKind::ObjCCast}}, + SanitizerHandler::InvalidObjCCast, + ArrayRef(StaticData), CurrentItem); + } + } + // Cast that value to the right type. CurrentItem = Builder.CreateBitCast(CurrentItem, convertedElementType, "currentitem"); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 1fc2ed76ca9e6..d794f4f0fa815 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -124,6 +124,7 @@ enum TypeEvaluationKind { SANITIZER_CHECK(FunctionTypeMismatch, function_type_mismatch, 1) \ SANITIZER_CHECK(ImplicitConversion, implicit_conversion, 0) \ SANITIZER_CHECK(InvalidBuiltin, invalid_builtin, 0) \ + SANITIZER_CHECK(InvalidObjCCast, invalid_objc_cast, 0) \ SANITIZER_CHECK(LoadInvalidValue, load_invalid_value, 0) \ SANITIZER_CHECK(MissingReturn, missing_return, 0) \ SANITIZER_CHECK(MulOverflow, mul_overflow, 0) \ diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 0b81152d57f6b..bcc9ffc7ff8f6 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -27,7 +27,8 @@ using namespace llvm::opt; static const SanitizerMask NeedsUbsanRt = SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | - SanitizerKind::CFI | SanitizerKind::FloatDivideByZero; + SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | + SanitizerKind::ObjCCast; static const SanitizerMask NeedsUbsanCxxRt = SanitizerKind::Vptr | SanitizerKind::CFI; static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr; @@ -48,11 +49,11 @@ static const SanitizerMask SupportsCoverage = SanitizerKind::DataFlow | SanitizerKind::Fuzzer | SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero | SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack | - SanitizerKind::Thread; + SanitizerKind::Thread | SanitizerKind::ObjCCast; static const SanitizerMask RecoverableByDefault = SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | - SanitizerKind::FloatDivideByZero; + SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast; static const SanitizerMask Unrecoverable = SanitizerKind::Unreachable | SanitizerKind::Return; static const SanitizerMask AlwaysRecoverable = @@ -62,7 +63,8 @@ static const SanitizerMask TrappingSupported = (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::UnsignedIntegerOverflow | SanitizerKind::ImplicitConversion | SanitizerKind::Nullability | SanitizerKind::LocalBounds | - SanitizerKind::CFI | SanitizerKind::FloatDivideByZero; + SanitizerKind::CFI | SanitizerKind::FloatDivideByZero | + SanitizerKind::ObjCCast; static const SanitizerMask TrappingDefault = SanitizerKind::CFI; static const SanitizerMask CFIClasses = SanitizerKind::CFIVCall | SanitizerKind::CFINVCall | diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 2e1190c34ea7a..7b879f8cb6521 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -2721,6 +2721,7 @@ SanitizerMask Darwin::getSupportedSanitizers() const { Res |= SanitizerKind::Fuzzer; Res |= SanitizerKind::FuzzerNoLink; Res |= SanitizerKind::Function; + Res |= SanitizerKind::ObjCCast; // Prior to 10.9, macOS shipped a version of the C++ standard library without // C++11 support. The same is true of iOS prior to version 5. These OS'es are diff --git a/clang/test/CodeGenObjC/for-in.m b/clang/test/CodeGenObjC/for-in.m index 26fe7922aee9f..20e89b33affaf 100644 --- a/clang/test/CodeGenObjC/for-in.m +++ b/clang/test/CodeGenObjC/for-in.m @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o %t +// RUN: %clang_cc1 %s -verify -o /dev/null +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin -emit-llvm -fsanitize=objc-cast -o - | FileCheck %s void p(const char*, ...); @@ -18,12 +19,26 @@ -(const char*) cString; #define L5(n) L4(n+0),L4(n+16) #define L6(n) L5(n+0),L5(n+32) +// CHECK-LABEL: define void @t0 void t0() { NSArray *array = [NSArray arrayWithObjects: L1(0), (void*)0]; p("array.length: %d\n", [array count]); unsigned index = 0; for (NSString *i in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}} + + // CHECK: [[expectedCls:%.*]] = load %struct._class_t*, {{.*}}, !nosanitize + // CHECK-NEXT: [[kindOfClassSel:%.*]] = load i8*, i8** @OBJC_SELECTOR_REFERENCES{{.*}}, !nosanitize + // CHECK-NEXT: [[expectedClsI8:%.*]] = bitcast %struct._class_t* [[expectedCls]] to i8*, !nosanitize + // CHECK-NEXT: [[isCls:%.*]] = call zeroext i1 bitcast {{.*}}@objc_msgSend to i1 (i8*, i8*, {{.*}})(i8* [[theItem:%.*]], i8* [[kindOfClassSel]], i8* [[expectedClsI8]]), !nosanitize + // CHECK: br i1 [[isCls]] + + // CHECK: ptrtoint i8* [[theItem]] to i64, !nosanitize + // CHECK-NEXT: call void @__ubsan_handle_invalid_objc_cast + // CHECK-NEXT: unreachable, !nosanitize + + // CHECK: bitcast i8* [[theItem]] + p("element %d: %s\n", index++, [i cString]); } } diff --git a/compiler-rt/lib/ubsan/ubsan_checks.inc b/compiler-rt/lib/ubsan/ubsan_checks.inc index 2c1529a7d92c5..846cd89ee19f8 100644 --- a/compiler-rt/lib/ubsan/ubsan_checks.inc +++ b/compiler-rt/lib/ubsan/ubsan_checks.inc @@ -37,6 +37,7 @@ UBSAN_CHECK(IntegerDivideByZero, "integer-divide-by-zero", "integer-divide-by-zero") UBSAN_CHECK(FloatDivideByZero, "float-divide-by-zero", "float-divide-by-zero") UBSAN_CHECK(InvalidBuiltin, "invalid-builtin-use", "invalid-builtin-use") +UBSAN_CHECK(InvalidObjCCast, "invalid-objc-cast", "invalid-objc-cast") UBSAN_CHECK(ImplicitUnsignedIntegerTruncation, "implicit-unsigned-integer-truncation", "implicit-unsigned-integer-truncation") diff --git a/compiler-rt/lib/ubsan/ubsan_handlers.cpp b/compiler-rt/lib/ubsan/ubsan_handlers.cpp index 7f6a46fb6cf08..e201e6bba2207 100644 --- a/compiler-rt/lib/ubsan/ubsan_handlers.cpp +++ b/compiler-rt/lib/ubsan/ubsan_handlers.cpp @@ -16,6 +16,7 @@ #include "ubsan_diag.h" #include "ubsan_flags.h" #include "ubsan_monitor.h" +#include "ubsan_value.h" #include "sanitizer_common/sanitizer_common.h" @@ -640,6 +641,36 @@ void __ubsan::__ubsan_handle_invalid_builtin_abort(InvalidBuiltinData *Data) { Die(); } +static void handleInvalidObjCCast(InvalidObjCCast *Data, ValueHandle Pointer, + ReportOptions Opts) { + SourceLocation Loc = Data->Loc.acquire(); + ErrorType ET = ErrorType::InvalidObjCCast; + + if (ignoreReport(Loc, Opts, ET)) + return; + + ScopedReport R(Opts, Loc, ET); + + const char *GivenClass = getObjCClassName(Pointer); + const char *GivenClassStr = GivenClass ? GivenClass : ""; + + Diag(Loc, DL_Error, ET, + "invalid ObjC cast, object is a '%0', but expected a %1") + << GivenClassStr << Data->ExpectedType; +} + +void __ubsan::__ubsan_handle_invalid_objc_cast(InvalidObjCCast *Data, + ValueHandle Pointer) { + GET_REPORT_OPTIONS(false); + handleInvalidObjCCast(Data, Pointer, Opts); +} +void __ubsan::__ubsan_handle_invalid_objc_cast_abort(InvalidObjCCast *Data, + ValueHandle Pointer) { + GET_REPORT_OPTIONS(true); + handleInvalidObjCCast(Data, Pointer, Opts); + Die(); +} + static void handleNonNullReturn(NonNullReturnData *Data, SourceLocation *LocPtr, ReportOptions Opts, bool IsAttr) { if (!LocPtr) diff --git a/compiler-rt/lib/ubsan/ubsan_handlers.h b/compiler-rt/lib/ubsan/ubsan_handlers.h index 22ca96422381c..219fb15de55fe 100644 --- a/compiler-rt/lib/ubsan/ubsan_handlers.h +++ b/compiler-rt/lib/ubsan/ubsan_handlers.h @@ -168,6 +168,14 @@ struct InvalidBuiltinData { /// Handle a builtin called in an invalid way. RECOVERABLE(invalid_builtin, InvalidBuiltinData *Data) +struct InvalidObjCCast { + SourceLocation Loc; + const TypeDescriptor &ExpectedType; +}; + +/// Handle an invalid ObjC cast. +RECOVERABLE(invalid_objc_cast, InvalidObjCCast *Data, ValueHandle Pointer) + struct NonNullReturnData { SourceLocation AttrLoc; }; diff --git a/compiler-rt/lib/ubsan/ubsan_value.cpp b/compiler-rt/lib/ubsan/ubsan_value.cpp index 60f0b5c993482..79c3ba991d398 100644 --- a/compiler-rt/lib/ubsan/ubsan_value.cpp +++ b/compiler-rt/lib/ubsan/ubsan_value.cpp @@ -16,9 +16,57 @@ #include "ubsan_value.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_libc.h" +#include "sanitizer_common/sanitizer_mutex.h" + +// TODO(dliew): Prefer '__APPLE__' here over 'SANITIZER_MAC', as the latter is +// unclear. rdar://58124919 tracks using a more obviously portable guard. +#if defined(__APPLE__) +#include +#endif using namespace __ubsan; +typedef const char *(*ObjCGetClassNameTy)(void *); + +const char *__ubsan::getObjCClassName(ValueHandle Pointer) { +#if defined(__APPLE__) + // We need to query the ObjC runtime for some information, but do not want + // to introduce a static dependency from the ubsan runtime onto ObjC. Try to + // grab a handle to the ObjC runtime used by the process. + static bool AttemptedDlopen = false; + static void *ObjCHandle = nullptr; + static void *ObjCObjectGetClassName = nullptr; + + // Prevent threads from racing to dlopen(). + static __sanitizer::StaticSpinMutex Lock; + { + __sanitizer::SpinMutexLock Guard(&Lock); + + if (!AttemptedDlopen) { + ObjCHandle = dlopen( + "/usr/lib/libobjc.A.dylib", + RTLD_LAZY // Only bind symbols when used. + | RTLD_LOCAL // Only make symbols available via the handle. + | RTLD_NOLOAD // Do not load the dylib, just grab a handle if the + // image is already loaded. + | RTLD_FIRST // Only search the image pointed-to by the handle. + ); + AttemptedDlopen = true; + if (!ObjCHandle) + return nullptr; + ObjCObjectGetClassName = dlsym(ObjCHandle, "object_getClassName"); + } + } + + if (!ObjCObjectGetClassName) + return nullptr; + + return ObjCGetClassNameTy(ObjCObjectGetClassName)((void *)Pointer); +#else + return nullptr; +#endif +} + SIntMax Value::getSIntValue() const { CHECK(getType().isSignedIntegerTy()); if (isInlineInt()) { diff --git a/compiler-rt/lib/ubsan/ubsan_value.h b/compiler-rt/lib/ubsan/ubsan_value.h index a216e3a147e91..e0957276dd241 100644 --- a/compiler-rt/lib/ubsan/ubsan_value.h +++ b/compiler-rt/lib/ubsan/ubsan_value.h @@ -135,6 +135,9 @@ class TypeDescriptor { /// \brief An opaque handle to a value. typedef uptr ValueHandle; +/// Returns the class name of the given ObjC object, or null if the name +/// cannot be found. +const char *getObjCClassName(ValueHandle Pointer); /// \brief Representation of an operand value provided by the instrumented code. /// diff --git a/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp b/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp index ed62ddd0fa348..8654c705cfbb0 100644 --- a/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp +++ b/compiler-rt/lib/ubsan_minimal/ubsan_minimal_handlers.cpp @@ -109,6 +109,7 @@ HANDLER(vla_bound_not_positive, "vla-bound-not-positive") HANDLER(float_cast_overflow, "float-cast-overflow") HANDLER(load_invalid_value, "load-invalid-value") HANDLER(invalid_builtin, "invalid-builtin") +HANDLER(invalid_objc_cast, "invalid-objc-cast") HANDLER(function_type_mismatch, "function-type-mismatch") HANDLER(implicit_conversion, "implicit-conversion") HANDLER(nonnull_arg, "nonnull-arg") diff --git a/compiler-rt/test/ubsan/TestCases/Misc/objc-cast.m b/compiler-rt/test/ubsan/TestCases/Misc/objc-cast.m new file mode 100644 index 0000000000000..f502e5f535372 --- /dev/null +++ b/compiler-rt/test/ubsan/TestCases/Misc/objc-cast.m @@ -0,0 +1,27 @@ +// REQUIRES: darwin +// +// RUN: %clang -framework Foundation -fsanitize=objc-cast %s -O1 -o %t +// RUN: %run %t 2>&1 | FileCheck %s +// +// RUN: %clang -framework Foundation -fsanitize=objc-cast -fno-sanitize-recover=objc-cast %s -O1 -o %t.trap +// RUN: not %run %t.trap 2>&1 | FileCheck %s + +#include + +int main() { + NSArray *arrayOfInt = [NSArray arrayWithObjects:@1, @2, @3, (void *)0]; + // CHECK: objc-cast.m:[[@LINE+1]]:{{.*}}: runtime error: invalid ObjC cast, object is a '__NSCFNumber', but expected a 'NSString' + for (NSString *str in arrayOfInt) { + NSLog(@"%@", str); + } + + NSArray *arrayOfStr = [NSArray arrayWithObjects:@"a", @"b", @"c", (void *)0]; + for (NSString *str in arrayOfStr) { + NSLog(@"%@", str); + } + + // The diagnostic should only be printed once. + // CHECK-NOT: runtime error + + return 0; +} From 42170b3b4e1f7d30b377a3da07c354feae9b852e Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Mon, 29 Jun 2020 23:56:01 +0000 Subject: [PATCH 161/771] [Sanitizers] Implement getcpuclockid interceptor Differential Revision: https://reviews.llvm.org/D83000 --- .../sanitizer_common_interceptors.inc | 18 +++++++++++++++++ .../sanitizer_platform_interceptors.h | 1 + .../TestCases/Linux/getcpuclockid.c | 20 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/getcpuclockid.c diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index ea9c71ba88032..4b02ad2670fef 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2199,6 +2199,23 @@ INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) { #define INIT_CLOCK_GETTIME #endif +#if SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID +INTERCEPTOR(int, clock_getcpuclockid, pid_t pid, __sanitizer_clockid_t *clockid) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, clock_getcpuclockid, pid, clockid); + int res = REAL(clock_getcpuclockid)(pid, clockid); + if (!res && clockid) { + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, clockid, sizeof *clockid); + } + return res; +} + +#define INIT_CLOCK_GETCPUCLOCKID \ + COMMON_INTERCEPT_FUNCTION(clock_getcpuclockid); +#else +#define INIT_CLOCK_GETCPUCLOCKID +#endif + #if SANITIZER_INTERCEPT_GETITIMER INTERCEPTOR(int, getitimer, int which, void *curr_value) { void *ctx; @@ -9914,6 +9931,7 @@ static void InitializeCommonInterceptors() { INIT_FGETGRENT_R; INIT_SETPWENT; INIT_CLOCK_GETTIME; + INIT_CLOCK_GETCPUCLOCKID; INIT_GETITIMER; INIT_TIME; INIT_GLOB; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 2d48e9d0ae1ad..e28bb937ae83d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -240,6 +240,7 @@ (SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) #define SANITIZER_INTERCEPT_CLOCK_GETTIME \ (SI_FREEBSD || SI_NETBSD || SI_OPENBSD || SI_LINUX || SI_SOLARIS) +#define SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID SI_LINUX #define SANITIZER_INTERCEPT_GETITIMER SI_POSIX #define SANITIZER_INTERCEPT_TIME SI_POSIX #define SANITIZER_INTERCEPT_GLOB SI_LINUX_NOT_ANDROID || SI_SOLARIS diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/getcpuclockid.c b/compiler-rt/test/sanitizer_common/TestCases/Linux/getcpuclockid.c new file mode 100644 index 0000000000000..6999a80b638e5 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/getcpuclockid.c @@ -0,0 +1,20 @@ +// RUN: %clang %s -Wl,-as-needed -o %t && %run %t +#include +#include +#include + +long cpu_ns() { + clockid_t clk; + struct timespec ts; + int res = clock_getcpuclockid(getpid(), &clk); + assert(!res); + res = clock_gettime(clk, &ts); + assert(!res); + return ts.tv_nsec; +} + +int main() { + long cpuns = cpu_ns(); + asm volatile ("" :: "r"(cpuns)); + return 0; +} From bf0d060fd4ea1221fdac154e3404e448709e31aa Mon Sep 17 00:00:00 2001 From: Jinsong Ji Date: Mon, 13 Jul 2020 21:19:18 +0000 Subject: [PATCH 162/771] [compiler-rt][MSAN][test] Update buffersize for UTF-8 to C convert This is exposed by https://reviews.llvm.org/D83486. When the host is UTF8, we may get n >10, causing assert failure. Increase the buffersize to support UTF-8 to C conversion. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D83719 --- compiler-rt/test/msan/strxfrm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/test/msan/strxfrm.cpp b/compiler-rt/test/msan/strxfrm.cpp index 94b8c70240907..d40b56b234cd3 100644 --- a/compiler-rt/test/msan/strxfrm.cpp +++ b/compiler-rt/test/msan/strxfrm.cpp @@ -7,7 +7,7 @@ #include int main(void) { - char q[10]; + char q[30]; size_t n = strxfrm(q, "abcdef", sizeof(q)); assert(n < sizeof(q)); __msan_check_mem_is_initialized(q, n + 1); From 528a1c56d976be83388782357b3b98711f7dafe0 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Mon, 13 Jul 2020 15:15:34 -0700 Subject: [PATCH 163/771] Check output in test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir, NFC --- .../Generic/MIRStripDebug/no-metadata-present.mir | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir b/llvm/test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir index 8952003384931..3df834845b404 100644 --- a/llvm/test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir +++ b/llvm/test/CodeGen/Generic/MIRStripDebug/no-metadata-present.mir @@ -1,7 +1,13 @@ -# RUN: llc -run-pass=mir-strip-debug -mir-strip-debugify-only=0 -o /dev/null %s +# RUN: llc -run-pass=mir-strip-debug -mir-strip-debugify-only=0 -o - %s | FileCheck %s + +# CHECK: name: test +# CHECK: body: | +# CHECK-NEXT: bb.0: +# CHECK-EMPTY: +# CHECK-NEXT: ... --- name: test body: | - bb.1: + bb.0: ... From 3d52b1e81b7b3891d9132d826d4889119fad7d00 Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Mon, 13 Jul 2020 15:17:03 -0700 Subject: [PATCH 164/771] Revert "[InstCombine] Drop debug loc in TryToSinkInstruction (reland)" This reverts commit 9649c2095f07a392bc2b2a93b5bd6c4c9bf5ba34. See discussion on the llvm-commits thread: if it's OK to preserve the location when sinking a call, it's probably OK to always preserve the location. --- .../InstCombine/InstructionCombining.cpp | 6 --- .../InstCombine/sink_to_unreachable_dbg.ll | 46 ------------------- 2 files changed, 52 deletions(-) delete mode 100644 llvm/test/Transforms/InstCombine/sink_to_unreachable_dbg.ll diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index d1c1e54188251..ec934906355d6 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3356,12 +3356,6 @@ static bool TryToSinkInstruction(Instruction *I, BasicBlock *DestBlock) { I->moveBefore(&*InsertPos); ++NumSunkInst; - // Drop the debug loc of non-inlinable instructions. This prevents - // single-stepping from going backwards. See HowToUpdateDebugInfo.rst for - // the full rationale. - if (!isa(I)) - I->setDebugLoc(DebugLoc()); - // Also sink all related debug uses from the source basic block. Otherwise we // get debug use before the def. Attempt to salvage debug uses first, to // maximise the range variables have location for. If we cannot salvage, then diff --git a/llvm/test/Transforms/InstCombine/sink_to_unreachable_dbg.ll b/llvm/test/Transforms/InstCombine/sink_to_unreachable_dbg.ll deleted file mode 100644 index e642276224b84..0000000000000 --- a/llvm/test/Transforms/InstCombine/sink_to_unreachable_dbg.ll +++ /dev/null @@ -1,46 +0,0 @@ -; RUN: opt -debugify -debugify-level=locations -instcombine -S < %s | FileCheck %s - -; CHECK-LABEL: @test1( -; CHECK: [[phi:%.*]] = phi i32 -; CHECK-NEXT: [[add:%.*]] = add i32 {{.*}}, 1{{$}} -; CHECK-NEXT: add i32 [[phi]], [[add]], !dbg -define i32 @test1(i32 %0, i1 %1) { - %3 = add i32 %0, 1 - br i1 %1, label %4, label %5 - -4: ; preds = %2 - br label %6 - -5: ; preds = %2 - br label %6 - -6: ; preds = %5, %4 - %7 = phi i32 [ 0, %4 ], [ 1, %5 ] - %8 = add i32 %7, %3 - ret i32 %8 -} - -; Function Attrs: nounwind readnone -declare i32 @external(i32) #0 - -; CHECK-LABEL: @test2( -; CHECK: [[phi:%.*]] = phi i32 -; CHECK-NEXT: [[add:%.*]] = call i32 @external(i32 {{.*}}), !dbg -; CHECK-NEXT: add i32 [[phi]], [[add]], !dbg -define i32 @test2(i32 %0, i1 %1) { - %3 = call i32 @external(i32 %0) - br i1 %1, label %4, label %5 - -4: ; preds = %2 - br label %6 - -5: ; preds = %2 - br label %6 - -6: ; preds = %5, %4 - %7 = phi i32 [ 0, %4 ], [ 1, %5 ] - %8 = add i32 %7, %3 - ret i32 %8 -} - -attributes #0 = { nounwind readnone } From bfa3b627c6832552a7808a9f0f7f9cab61c7ea1a Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Tue, 7 Jul 2020 21:21:13 +0000 Subject: [PATCH 165/771] [InstCombine] Erase attribute lists for simplified libcalls Currently, a transformation like pow(2.0, x) -> exp2(x) copies the pow attribute list verbatim and applies it to exp2. This works out fine when the attribute list is empty, but when it isn't clang may error due due to the mismatch. The source function and destination don't necessarily have anything to do with one another, attribute-wise. So it makes sense to remove the attribute lists (this is similar to what IPO does in this situation). This was discovered after implementing the `noundef` param attribute. Differential Revision: https://reviews.llvm.org/D82820 --- .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 9 ++++---- .../test/Transforms/InstCombine/pow_fp_int.ll | 6 ++--- .../InstCombine/simplify-libcalls.ll | 22 +++++++++++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 6ad8bc6e09426..cfcc3454a2102 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1448,7 +1448,7 @@ static Value *getIntToFPVal(Value *I2F, IRBuilderBase &B) { /// exp10(x) for pow(10.0, x); exp2(log2(n) * x) for pow(n, x). Value *LibCallSimplifier::replacePowWithExp(CallInst *Pow, IRBuilderBase &B) { Value *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); - AttributeList Attrs = Pow->getCalledFunction()->getAttributes(); + AttributeList Attrs; // Attributes are only meaningful on the original call Module *Mod = Pow->getModule(); Type *Ty = Pow->getType(); bool Ignored; @@ -1615,7 +1615,7 @@ static Value *getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno, /// Use square root in place of pow(x, +/-0.5). Value *LibCallSimplifier::replacePowWithSqrt(CallInst *Pow, IRBuilderBase &B) { Value *Sqrt, *Base = Pow->getArgOperand(0), *Expo = Pow->getArgOperand(1); - AttributeList Attrs = Pow->getCalledFunction()->getAttributes(); + AttributeList Attrs; // Attributes are only meaningful on the original call Module *Mod = Pow->getModule(); Type *Ty = Pow->getType(); @@ -1785,6 +1785,7 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilderBase &B) { Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { Function *Callee = CI->getCalledFunction(); + AttributeList Attrs; // Attributes are only meaningful on the original call StringRef Name = Callee->getName(); Value *Ret = nullptr; if (UnsafeFPShrink && Name == TLI->getName(LibFunc_exp2) && @@ -1801,7 +1802,7 @@ Value *LibCallSimplifier::optimizeExp2(CallInst *CI, IRBuilderBase &B) { if (Value *Exp = getIntToFPVal(Op, B)) return emitBinaryFloatFnCall(ConstantFP::get(Ty, 1.0), Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl, - B, CI->getCalledFunction()->getAttributes()); + B, Attrs); } return Ret; @@ -1836,7 +1837,7 @@ Value *LibCallSimplifier::optimizeFMinFMax(CallInst *CI, IRBuilderBase &B) { Value *LibCallSimplifier::optimizeLog(CallInst *Log, IRBuilderBase &B) { Function *LogFn = Log->getCalledFunction(); - AttributeList Attrs = LogFn->getAttributes(); + AttributeList Attrs; // Attributes are only meaningful on the original call StringRef LogNm = LogFn->getName(); Intrinsic::ID LogID = LogFn->getIntrinsicID(); Module *Mod = Log->getModule(); diff --git a/llvm/test/Transforms/InstCombine/pow_fp_int.ll b/llvm/test/Transforms/InstCombine/pow_fp_int.ll index b4117d4ca0e0e..48297589ad91e 100644 --- a/llvm/test/Transforms/InstCombine/pow_fp_int.ll +++ b/llvm/test/Transforms/InstCombine/pow_fp_int.ll @@ -51,7 +51,7 @@ define double @pow_uitofp_double_const_base_fast(i31 %x) { define double @pow_sitofp_double_const_base_2_fast(i32 %x) { ; CHECK-LABEL: @pow_sitofp_double_const_base_2_fast( -; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) #1 +; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double ; CHECK-NEXT: ret double [[RES]] ; @@ -78,7 +78,7 @@ define double @pow_sitofp_double_const_base_power_of_2_fast(i32 %x) { define double @pow_uitofp_const_base_2_fast(i31 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_2_fast( ; CHECK-NEXT: [[TMP1:%.*]] = zext i31 [[X:%.*]] to i32 -; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) #1 +; CHECK-NEXT: [[LDEXPF:%.*]] = call afn float @ldexpf(float 1.000000e+00, i32 [[TMP1]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double ; CHECK-NEXT: ret double [[RES]] ; @@ -343,7 +343,7 @@ define double @pow_uitofp_const_base_no_fast(i32 %x) { define double @pow_sitofp_const_base_2_no_fast(i32 %x) { ; CHECK-LABEL: @pow_sitofp_const_base_2_no_fast( -; CHECK-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) #1 +; CHECK-NEXT: [[LDEXPF:%.*]] = call float @ldexpf(float 1.000000e+00, i32 [[X:%.*]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[LDEXPF]] to double ; CHECK-NEXT: ret double [[RES]] ; diff --git a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll index d31c3b17ac62c..d212bcd8ff767 100644 --- a/llvm/test/Transforms/InstCombine/simplify-libcalls.ll +++ b/llvm/test/Transforms/InstCombine/simplify-libcalls.ll @@ -175,6 +175,28 @@ define i32 @fake_toascii(i8 %x) { ret i32 %y } +declare double @pow(double, double) +declare double @exp2(double) + +; check to make sure only the correct libcall attributes are used +define double @fake_exp2(double %x) { +; CHECK-LABEL: @fake_exp2( +; CHECK-NEXT: [[Y:%.*]] = call double @exp2(double %x) +; CHECK-NEXT: ret double [[Y]] + + %y = call inreg double @pow(double inreg 2.0, double inreg %x) + ret double %y +} +define double @fake_ldexp(i32 %x) { +; CHECK-LABEL: @fake_ldexp( +; CHECK-NEXT: [[Z:%.*]] = call double @ldexp(double 1.0{{.*}}, i32 %x) +; CHECK-NEXT: ret double [[Z]] + + %y = sitofp i32 %x to double + %z = call inreg double @exp2(double %y) + ret double %z +} + attributes #0 = { nobuiltin } attributes #1 = { builtin } From 10aa0d7bbc12bf86958bc40943e37b46c6eed04a Mon Sep 17 00:00:00 2001 From: Dokyung Song Date: Mon, 13 Jul 2020 21:56:02 +0000 Subject: [PATCH 166/771] [compiler-rt] Fix compiler warnings and runtime errors in sanitizer RT strxfrm(_l) test cases. Summary: Fixed an implicit definition warning by including . Also fixed run-time assertions that the return value of strxfrm_l calls is less than the buffer size by increasing the size of the referenced buffer. Reviewers: morehouse Reviewed By: morehouse Subscribers: dberris, #sanitizers Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D83593 --- compiler-rt/test/msan/__strxfrm_l.cpp | 2 +- compiler-rt/test/sanitizer_common/TestCases/Posix/strxfrm.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler-rt/test/msan/__strxfrm_l.cpp b/compiler-rt/test/msan/__strxfrm_l.cpp index c4eb10efb3e0b..9766d33056857 100644 --- a/compiler-rt/test/msan/__strxfrm_l.cpp +++ b/compiler-rt/test/msan/__strxfrm_l.cpp @@ -10,7 +10,7 @@ extern "C" decltype(strxfrm_l) __strxfrm_l; int main(void) { - char q[10]; + char q[100]; locale_t loc = newlocale(LC_ALL_MASK, "", (locale_t)0); size_t n = __strxfrm_l(q, "qwerty", sizeof(q), loc); assert(n < sizeof(q)); diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/strxfrm.c b/compiler-rt/test/sanitizer_common/TestCases/Posix/strxfrm.c index c28eb65b7d4f0..d08af1b3565fd 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Posix/strxfrm.c +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/strxfrm.c @@ -3,16 +3,16 @@ #include #include -#include +#include int main(int argc, char **argv) { char q[10]; size_t n = strxfrm(q, "abcdef", sizeof(q)); assert(n < sizeof(q)); - char q2[10]; + char q2[100]; locale_t loc = newlocale(LC_ALL_MASK, "", (locale_t)0); - n = strxfrm_l(q2, L"qwerty", sizeof(q), loc); + n = strxfrm_l(q2, "qwerty", sizeof(q2), loc); assert(n < sizeof(q2)); freelocale(loc); From 004bf35ba04873dc9ab1408bce0d6f2fed03b0ea Mon Sep 17 00:00:00 2001 From: Vedant Kumar Date: Mon, 13 Jul 2020 15:40:05 -0700 Subject: [PATCH 167/771] Update ubsan_interface.inc for D71491 This should address the bot failure here: http://lab.llvm.org:8011/builders/sanitizer-windows/builds/66309/ --- compiler-rt/lib/ubsan/ubsan_interface.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler-rt/lib/ubsan/ubsan_interface.inc b/compiler-rt/lib/ubsan/ubsan_interface.inc index 1e44bc2171ded..503cc613b4544 100644 --- a/compiler-rt/lib/ubsan/ubsan_interface.inc +++ b/compiler-rt/lib/ubsan/ubsan_interface.inc @@ -27,6 +27,8 @@ INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion) INTERFACE_FUNCTION(__ubsan_handle_implicit_conversion_abort) INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin) INTERFACE_FUNCTION(__ubsan_handle_invalid_builtin_abort) +INTERFACE_FUNCTION(__ubsan_handle_objc_cast_check) +INTERFACE_FUNCTION(__ubsan_handle_objc_cast_check_abort) INTERFACE_FUNCTION(__ubsan_handle_load_invalid_value) INTERFACE_FUNCTION(__ubsan_handle_load_invalid_value_abort) INTERFACE_FUNCTION(__ubsan_handle_missing_return) From d9067dca7ba7cda97a86ec22106e06ffc700ecbf Mon Sep 17 00:00:00 2001 From: Kiran Chandramohan Date: Mon, 13 Jul 2020 23:13:04 +0100 Subject: [PATCH 168/771] Lowering of OpenMP Parallel operation to LLVM IR 1/n This patch introduces lowering of the OpenMP parallel operation to LLVM IR using the OpenMPIRBuilder. Functions topologicalSort and connectPhiNodes are generalised so that they work with operations also. connectPhiNodes is also made static. Lowering works for a parallel region with multiple blocks. Clauses and arguments of the OpenMP operation are not handled. Reviewed By: rriddle, anchu-rajendran Differential Revision: https://reviews.llvm.org/D81660 --- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 5 +- .../mlir/Target/LLVMIR/ModuleTranslation.h | 3 +- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 231 ++++++++++++------ mlir/test/Target/openmp-llvm.mlir | 46 ++++ 4 files changed, 210 insertions(+), 75 deletions(-) diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td index 3be6c97322b58..642282f8af181 100644 --- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -24,7 +24,6 @@ def OpenMP_Dialect : Dialect { class OpenMP_Op traits = []> : Op; - //===----------------------------------------------------------------------===// // 2.6 parallel Construct //===----------------------------------------------------------------------===// @@ -81,8 +80,8 @@ def ParallelOp : OpenMP_Op<"parallel", [AttrSizedOperandSegments]> { of the parallel region. }]; - let arguments = (ins Optional:$if_expr_var, - Optional:$num_threads_var, + let arguments = (ins Optional:$if_expr_var, + Optional:$num_threads_var, OptionalAttr:$default_val, Variadic:$private_vars, Variadic:$firstprivate_vars, diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h index 3a701018beb54..e44ae976e0dd0 100644 --- a/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h +++ b/mlir/include/mlir/Target/LLVMIR/ModuleTranslation.h @@ -87,6 +87,8 @@ class ModuleTranslation { llvm::IRBuilder<> &builder); virtual LogicalResult convertOmpOperation(Operation &op, llvm::IRBuilder<> &builder); + virtual LogicalResult convertOmpParallel(Operation &op, + llvm::IRBuilder<> &builder); static std::unique_ptr prepareLLVMModule(Operation *m); /// A helper to look up remapped operands in the value remapping table. @@ -100,7 +102,6 @@ class ModuleTranslation { LogicalResult convertFunctions(); LogicalResult convertGlobals(); LogicalResult convertOneFunction(LLVMFuncOp func); - void connectPHINodes(LLVMFuncOp func); LogicalResult convertBlock(Block &bb, bool ignoreArguments); llvm::Constant *getLLVMConstant(llvm::Type *llvmType, Attribute attr, diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp index 657aa84afe1c2..0defea6bbbb95 100644 --- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp +++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp @@ -25,11 +25,13 @@ #include "llvm/ADT/SetVector.h" #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Cloning.h" using namespace mlir; @@ -304,7 +306,160 @@ ModuleTranslation::ModuleTranslation(Operation *module, assert(satisfiesLLVMModule(mlirModule) && "mlirModule should honor LLVM's module semantics."); } -ModuleTranslation::~ModuleTranslation() {} +ModuleTranslation::~ModuleTranslation() { + if (ompBuilder) + ompBuilder->finalize(); +} + +/// Get the SSA value passed to the current block from the terminator operation +/// of its predecessor. +static Value getPHISourceValue(Block *current, Block *pred, + unsigned numArguments, unsigned index) { + Operation &terminator = *pred->getTerminator(); + if (isa(terminator)) + return terminator.getOperand(index); + + // For conditional branches, we need to check if the current block is reached + // through the "true" or the "false" branch and take the relevant operands. + auto condBranchOp = dyn_cast(terminator); + assert(condBranchOp && + "only branch operations can be terminators of a block that " + "has successors"); + assert((condBranchOp.getSuccessor(0) != condBranchOp.getSuccessor(1)) && + "successors with arguments in LLVM conditional branches must be " + "different blocks"); + + return condBranchOp.getSuccessor(0) == current + ? condBranchOp.trueDestOperands()[index] + : condBranchOp.falseDestOperands()[index]; +} + +/// Connect the PHI nodes to the results of preceding blocks. +template +static void +connectPHINodes(T &func, const DenseMap &valueMapping, + const DenseMap &blockMapping) { + // Skip the first block, it cannot be branched to and its arguments correspond + // to the arguments of the LLVM function. + for (auto it = std::next(func.begin()), eit = func.end(); it != eit; ++it) { + Block *bb = &*it; + llvm::BasicBlock *llvmBB = blockMapping.lookup(bb); + auto phis = llvmBB->phis(); + auto numArguments = bb->getNumArguments(); + assert(numArguments == std::distance(phis.begin(), phis.end())); + for (auto &numberedPhiNode : llvm::enumerate(phis)) { + auto &phiNode = numberedPhiNode.value(); + unsigned index = numberedPhiNode.index(); + for (auto *pred : bb->getPredecessors()) { + phiNode.addIncoming(valueMapping.lookup(getPHISourceValue( + bb, pred, numArguments, index)), + blockMapping.lookup(pred)); + } + } + } +} + +// TODO: implement an iterative version +static void topologicalSortImpl(llvm::SetVector &blocks, Block *b) { + blocks.insert(b); + for (Block *bb : b->getSuccessors()) { + if (blocks.count(bb) == 0) + topologicalSortImpl(blocks, bb); + } +} + +/// Sort function blocks topologically. +template +static llvm::SetVector topologicalSort(T &f) { + // For each blocks that has not been visited yet (i.e. that has no + // predecessors), add it to the list and traverse its successors in DFS + // preorder. + llvm::SetVector blocks; + for (Block &b : f) { + if (blocks.count(&b) == 0) + topologicalSortImpl(blocks, &b); + } + assert(blocks.size() == f.getBlocks().size() && "some blocks are not sorted"); + + return blocks; +} + +/// Convert the OpenMP parallel Operation to LLVM IR. +LogicalResult +ModuleTranslation::convertOmpParallel(Operation &opInst, + llvm::IRBuilder<> &builder) { + using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy; + + auto bodyGenCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP, + llvm::BasicBlock &continuationIP) { + llvm::LLVMContext &llvmContext = llvmModule->getContext(); + + llvm::BasicBlock *codeGenIPBB = codeGenIP.getBlock(); + llvm::Instruction *codeGenIPBBTI = codeGenIPBB->getTerminator(); + + builder.SetInsertPoint(codeGenIPBB); + + for (auto ®ion : opInst.getRegions()) { + for (auto &bb : region) { + auto *llvmBB = llvm::BasicBlock::Create( + llvmContext, "omp.par.region", codeGenIP.getBlock()->getParent()); + blockMapping[&bb] = llvmBB; + } + + // Then, convert blocks one by one in topological order to ensure + // defs are converted before uses. + llvm::SetVector blocks = topologicalSort(region); + for (auto indexedBB : llvm::enumerate(blocks)) { + Block *bb = indexedBB.value(); + llvm::BasicBlock *curLLVMBB = blockMapping[bb]; + if (bb->isEntryBlock()) + codeGenIPBBTI->setSuccessor(0, curLLVMBB); + + // TODO: Error not returned up the hierarchy + if (failed( + convertBlock(*bb, /*ignoreArguments=*/indexedBB.index() == 0))) + return; + + // If this block has the terminator then add a jump to + // continuation bb + for (auto &op : *bb) { + if (isa(op)) { + builder.SetInsertPoint(curLLVMBB); + builder.CreateBr(&continuationIP); + } + } + } + // Finally, after all blocks have been traversed and values mapped, + // connect the PHI nodes to the results of preceding blocks. + connectPHINodes(region, valueMapping, blockMapping); + } + }; + + // TODO: Perform appropriate actions according to the data-sharing + // attribute (shared, private, firstprivate, ...) of variables. + // Currently defaults to shared. + auto privCB = [&](InsertPointTy allocaIP, InsertPointTy codeGenIP, + llvm::Value &vPtr, + llvm::Value *&replacementValue) -> InsertPointTy { + replacementValue = &vPtr; + + return codeGenIP; + }; + + // TODO: Perform finalization actions for variables. This has to be + // called for variables which have destructors/finalizers. + auto finiCB = [&](InsertPointTy codeGenIP) {}; + + // TODO: The various operands of parallel operation are not handled. + // Parallel operation is created with some default options for now. + llvm::Value *ifCond = nullptr; + llvm::Value *numThreads = nullptr; + bool isCancellable = false; + builder.restoreIP(ompBuilder->CreateParallel( + builder, bodyGenCB, privCB, finiCB, ifCond, numThreads, + llvm::omp::OMP_PROC_BIND_default, isCancellable)); + return success(); +} /// Given an OpenMP MLIR operation, create the corresponding LLVM IR /// (including OpenMP runtime calls). @@ -340,6 +495,9 @@ ModuleTranslation::convertOmpOperation(Operation &opInst, ompBuilder->CreateFlush(builder.saveIP()); return success(); }) + .Case([&](omp::TerminatorOp) { return success(); }) + .Case( + [&](omp::ParallelOp) { return convertOmpParallel(opInst, builder); }) .Default([&](Operation *inst) { return inst->emitError("unsupported OpenMP operation: ") << inst->getName(); @@ -556,75 +714,6 @@ LogicalResult ModuleTranslation::convertGlobals() { return success(); } -/// Get the SSA value passed to the current block from the terminator operation -/// of its predecessor. -static Value getPHISourceValue(Block *current, Block *pred, - unsigned numArguments, unsigned index) { - auto &terminator = *pred->getTerminator(); - if (isa(terminator)) { - return terminator.getOperand(index); - } - - // For conditional branches, we need to check if the current block is reached - // through the "true" or the "false" branch and take the relevant operands. - auto condBranchOp = dyn_cast(terminator); - assert(condBranchOp && - "only branch operations can be terminators of a block that " - "has successors"); - assert((condBranchOp.getSuccessor(0) != condBranchOp.getSuccessor(1)) && - "successors with arguments in LLVM conditional branches must be " - "different blocks"); - - return condBranchOp.getSuccessor(0) == current - ? condBranchOp.trueDestOperands()[index] - : condBranchOp.falseDestOperands()[index]; -} - -void ModuleTranslation::connectPHINodes(LLVMFuncOp func) { - // Skip the first block, it cannot be branched to and its arguments correspond - // to the arguments of the LLVM function. - for (auto it = std::next(func.begin()), eit = func.end(); it != eit; ++it) { - Block *bb = &*it; - llvm::BasicBlock *llvmBB = blockMapping.lookup(bb); - auto phis = llvmBB->phis(); - auto numArguments = bb->getNumArguments(); - assert(numArguments == std::distance(phis.begin(), phis.end())); - for (auto &numberedPhiNode : llvm::enumerate(phis)) { - auto &phiNode = numberedPhiNode.value(); - unsigned index = numberedPhiNode.index(); - for (auto *pred : bb->getPredecessors()) { - phiNode.addIncoming(valueMapping.lookup(getPHISourceValue( - bb, pred, numArguments, index)), - blockMapping.lookup(pred)); - } - } - } -} - -// TODO: implement an iterative version -static void topologicalSortImpl(llvm::SetVector &blocks, Block *b) { - blocks.insert(b); - for (Block *bb : b->getSuccessors()) { - if (blocks.count(bb) == 0) - topologicalSortImpl(blocks, bb); - } -} - -/// Sort function blocks topologically. -static llvm::SetVector topologicalSort(LLVMFuncOp f) { - // For each blocks that has not been visited yet (i.e. that has no - // predecessors), add it to the list and traverse its successors in DFS - // preorder. - llvm::SetVector blocks; - for (Block &b : f) { - if (blocks.count(&b) == 0) - topologicalSortImpl(blocks, &b); - } - assert(blocks.size() == f.getBlocks().size() && "some blocks are not sorted"); - - return blocks; -} - /// Attempts to add an attribute identified by `key`, optionally with the given /// `value` to LLVM function `llvmFunc`. Reports errors at `loc` if any. If the /// attribute has a kind known to LLVM IR, create the attribute of this kind, @@ -772,7 +861,7 @@ LogicalResult ModuleTranslation::convertOneFunction(LLVMFuncOp func) { // Finally, after all blocks have been traversed and values mapped, connect // the PHI nodes to the results of preceding blocks. - connectPHINodes(func); + connectPHINodes(func, valueMapping, blockMapping); return success(); } diff --git a/mlir/test/Target/openmp-llvm.mlir b/mlir/test/Target/openmp-llvm.mlir index ddfc2a4cf7868..c8acd8022b2bf 100644 --- a/mlir/test/Target/openmp-llvm.mlir +++ b/mlir/test/Target/openmp-llvm.mlir @@ -32,3 +32,49 @@ llvm.func @test_flush_construct(%arg0: !llvm.i32) { // CHECK-NEXT: ret void llvm.return } + +// CHECK-LABEL: define void @test_omp_parallel_1() +llvm.func @test_omp_parallel_1() -> () { + // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_1:.*]] to {{.*}} + omp.parallel { + omp.barrier + omp.terminator + } + + llvm.return +} + +// CHECK: define internal void @[[OMP_OUTLINED_FN_1]] + // CHECK: call void @__kmpc_barrier + +llvm.func @body(!llvm.i64) + +// CHECK-LABEL: define void @test_omp_parallel_2() +llvm.func @test_omp_parallel_2() -> () { + // CHECK: call void{{.*}}@__kmpc_fork_call{{.*}}@[[OMP_OUTLINED_FN_2:.*]] to {{.*}} + omp.parallel { + ^bb0: + %0 = llvm.mlir.constant(1 : index) : !llvm.i64 + %1 = llvm.mlir.constant(42 : index) : !llvm.i64 + llvm.call @body(%0) : (!llvm.i64) -> () + llvm.call @body(%1) : (!llvm.i64) -> () + llvm.br ^bb1 + + ^bb1: + %2 = llvm.add %0, %1 : !llvm.i64 + llvm.call @body(%2) : (!llvm.i64) -> () + omp.terminator + } + llvm.return +} + +// CHECK: define internal void @[[OMP_OUTLINED_FN_2]] + // CHECK-LABEL: omp.par.region: + // CHECK: br label %omp.par.region1 + // CHECK-LABEL: omp.par.region1: + // CHECK: call void @body(i64 1) + // CHECK: call void @body(i64 42) + // CHECK: br label %omp.par.region2 + // CHECK-LABEL: omp.par.region2: + // CHECK: call void @body(i64 43) + // CHECK: br label %omp.par.pre_finalize From e958379581e5845572c21b8871873fcb0b15743e Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Mon, 13 Jul 2020 16:03:10 -0700 Subject: [PATCH 169/771] Fold the opt size check into the assert to silence an unused variable warning. --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index e91828bd17078..3cd80cb04ab84 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -182,9 +182,8 @@ namespace { "indirect-tls-seg-refs"); // OptFor[Min]Size are used in pattern predicates that isel is matching. - bool OptForSize = MF.getFunction().hasOptSize(); OptForMinSize = MF.getFunction().hasMinSize(); - assert((!OptForMinSize || OptForSize) && + assert((!OptForMinSize || MF.getFunction().hasOptSize()) && "OptForMinSize implies OptForSize"); SelectionDAGISel::runOnMachineFunction(MF); From 8d09f20798ac180b1749276bff364682ce0196ab Mon Sep 17 00:00:00 2001 From: Tyker Date: Tue, 14 Jul 2020 00:52:37 +0200 Subject: [PATCH 170/771] [AssumeBundles] Use operand bundles to encode alignment assumptions Summary: NOTE: There is a mailing list discussion on this: http://lists.llvm.org/pipermail/llvm-dev/2019-December/137632.html Complemantary to the assumption outliner prototype in D71692, this patch shows how we could simplify the code emitted for an alignemnt assumption. The generated code is smaller, less fragile, and it makes it easier to recognize the additional use as a "assumption use". As mentioned in D71692 and on the mailing list, we could adopt this scheme, and similar schemes for other patterns, without adopting the assumption outlining. Reviewers: hfinkel, xbolva00, lebedev.ri, nikic, rjmccall, spatel, jdoerfert, sstefan1 Reviewed By: jdoerfert Subscribers: thopre, yamauchi, kuter, fhahn, merge_guards_bot, hiraditya, bollu, rkruppe, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D71739 --- clang/lib/CodeGen/CodeGenFunction.cpp | 36 +++++- clang/test/CodeGen/align_value.cpp | 30 +---- clang/test/CodeGen/alloc-align-attr.c | 44 ++----- ...ssume-aligned-and-alloc-align-attributes.c | 8 +- clang/test/CodeGen/builtin-align-array.c | 32 ++--- clang/test/CodeGen/builtin-align.c | 24 +--- clang/test/CodeGen/builtin-assume-aligned.c | 32 +---- ...mption-attribute-align_value-on-lvalue.cpp | 8 +- ...tion-attribute-align_value-on-paramvar.cpp | 2 +- ...ibute-alloc_align-on-function-variable.cpp | 10 +- ...tion-attribute-alloc_align-on-function.cpp | 2 +- ...-assume_aligned-on-function-two-params.cpp | 10 +- ...n-attribute-assume_aligned-on-function.cpp | 2 +- ...n_assume_aligned-three-params-variable.cpp | 10 +- ...on-builtin_assume_aligned-three-params.cpp | 10 +- ...tion-builtin_assume_aligned-two-params.cpp | 8 +- .../catch-alignment-assumption-openmp.cpp | 8 +- .../non-power-of-2-alignment-assumptions.c | 13 +- clang/test/OpenMP/simd_codegen.cpp | 16 --- clang/test/OpenMP/simd_metadata.c | 117 +++++++---------- ...s_distribute_parallel_for_simd_codegen.cpp | 5 +- llvm/include/llvm/IR/IRBuilder.h | 28 ++-- .../Scalar/AlignmentFromAssumptions.h | 6 +- llvm/lib/Analysis/AssumeBundleQueries.cpp | 13 +- llvm/lib/IR/IRBuilder.cpp | 77 ++++------- llvm/lib/IR/Verifier.cpp | 23 +++- .../InstCombine/InstCombineCalls.cpp | 15 ++- .../Scalar/AlignmentFromAssumptions.cpp | 121 +++++------------- .../AlignmentFromAssumptions/simple.ll | 75 ++++------- .../AlignmentFromAssumptions/simple32.ll | 114 ++++------------- llvm/test/Transforms/Inline/align.ll | 15 +-- llvm/test/Transforms/InstCombine/assume.ll | 1 + .../inlining-alignment-assumptions.ll | 27 +--- llvm/test/Verifier/assume-bundles.ll | 16 ++- .../Analysis/AssumeBundleQueriesTest.cpp | 38 ++++++ 35 files changed, 369 insertions(+), 627 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 8ce488f35dd32..4a7c84562deef 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -2154,13 +2154,39 @@ void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue, SourceLocation AssumptionLoc, llvm::Value *Alignment, llvm::Value *OffsetValue) { - llvm::Value *TheCheck; - llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption( - CGM.getDataLayout(), PtrValue, Alignment, OffsetValue, &TheCheck); + if (Alignment->getType() != IntPtrTy) + Alignment = + Builder.CreateIntCast(Alignment, IntPtrTy, false, "casted.align"); + if (OffsetValue && OffsetValue->getType() != IntPtrTy) + OffsetValue = + Builder.CreateIntCast(OffsetValue, IntPtrTy, true, "casted.offset"); + llvm::Value *TheCheck = nullptr; if (SanOpts.has(SanitizerKind::Alignment)) { - emitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, Alignment, - OffsetValue, TheCheck, Assumption); + llvm::Value *PtrIntValue = + Builder.CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); + + if (OffsetValue) { + bool IsOffsetZero = false; + if (const auto *CI = dyn_cast(OffsetValue)) + IsOffsetZero = CI->isZero(); + + if (!IsOffsetZero) + PtrIntValue = Builder.CreateSub(PtrIntValue, OffsetValue, "offsetptr"); + } + + llvm::Value *Zero = llvm::ConstantInt::get(IntPtrTy, 0); + llvm::Value *Mask = + Builder.CreateSub(Alignment, llvm::ConstantInt::get(IntPtrTy, 1)); + llvm::Value *MaskedPtr = Builder.CreateAnd(PtrIntValue, Mask, "maskedptr"); + TheCheck = Builder.CreateICmpEQ(MaskedPtr, Zero, "maskcond"); } + llvm::Instruction *Assumption = Builder.CreateAlignmentAssumption( + CGM.getDataLayout(), PtrValue, Alignment, OffsetValue); + + if (!SanOpts.has(SanitizerKind::Alignment)) + return; + emitAlignmentAssumptionCheck(PtrValue, Ty, Loc, AssumptionLoc, Alignment, + OffsetValue, TheCheck, Assumption); } void CodeGenFunction::emitAlignmentAssumption(llvm::Value *PtrValue, diff --git a/clang/test/CodeGen/align_value.cpp b/clang/test/CodeGen/align_value.cpp index acbfbaf2ba5c7..a18cb651fe4c0 100644 --- a/clang/test/CodeGen/align_value.cpp +++ b/clang/test/CodeGen/align_value.cpp @@ -29,10 +29,7 @@ struct ad_struct { // CHECK-NEXT: [[TMP0:%.*]] = load %struct.ad_struct*, %struct.ad_struct** [[X_ADDR]], align 8 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_AD_STRUCT:%.*]], %struct.ad_struct* [[TMP0]], i32 0, i32 0 // CHECK-NEXT: [[TMP1:%.*]] = load double*, double** [[A]], align 8 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint double* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 63 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[TMP1]], i64 64) ] // CHECK-NEXT: ret double* [[TMP1]] // double *foo(ad_struct& x) { @@ -48,10 +45,7 @@ double *foo(ad_struct& x) { // CHECK-NEXT: [[TMP0:%.*]] = load %struct.ad_struct*, %struct.ad_struct** [[X_ADDR]], align 8 // CHECK-NEXT: [[A:%.*]] = getelementptr inbounds [[STRUCT_AD_STRUCT:%.*]], %struct.ad_struct* [[TMP0]], i32 0, i32 0 // CHECK-NEXT: [[TMP1:%.*]] = load double*, double** [[A]], align 8 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint double* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 63 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[TMP1]], i64 64) ] // CHECK-NEXT: ret double* [[TMP1]] // double *goo(ad_struct *x) { @@ -66,10 +60,7 @@ double *goo(ad_struct *x) { // CHECK-NEXT: store double** [[X]], double*** [[X_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load double**, double*** [[X_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load double*, double** [[TMP0]], align 8 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint double* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 63 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[TMP1]], i64 64) ] // CHECK-NEXT: ret double* [[TMP1]] // double *bar(aligned_double *x) { @@ -84,10 +75,7 @@ double *bar(aligned_double *x) { // CHECK-NEXT: store double** [[X]], double*** [[X_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load double**, double*** [[X_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = load double*, double** [[TMP0]], align 8 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint double* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 63 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[TMP1]], i64 64) ] // CHECK-NEXT: ret double* [[TMP1]] // double *car(aligned_double &x) { @@ -103,10 +91,7 @@ double *car(aligned_double &x) { // CHECK-NEXT: [[TMP0:%.*]] = load double**, double*** [[X_ADDR]], align 8 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double*, double** [[TMP0]], i64 5 // CHECK-NEXT: [[TMP1:%.*]] = load double*, double** [[ARRAYIDX]], align 8 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint double* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 63 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[TMP1]], i64 64) ] // CHECK-NEXT: ret double* [[TMP1]] // double *dar(aligned_double *x) { @@ -118,10 +103,7 @@ aligned_double eep(); // CHECK-LABEL: define {{[^@]+}}@_Z3retv() #0 // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call double* @_Z3eepv() -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint double* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 63 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[CALL]], i64 64) ] // CHECK-NEXT: ret double* [[CALL]] // double *ret() { diff --git a/clang/test/CodeGen/alloc-align-attr.c b/clang/test/CodeGen/alloc-align-attr.c index 9517c50dbb1db..44a57291b47c8 100644 --- a/clang/test/CodeGen/alloc-align-attr.c +++ b/clang/test/CodeGen/alloc-align-attr.c @@ -11,12 +11,8 @@ __INT32_TYPE__*m1(__INT32_TYPE__ i) __attribute__((alloc_align(1))); // CHECK-NEXT: store i32 [[A]], i32* [[A_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_ADDR]], align 4 // CHECK-NEXT: [[CALL:%.*]] = call i32* @m1(i32 [[TMP0]]) -// CHECK-NEXT: [[ALIGNMENTCAST:%.*]] = zext i32 [[TMP0]] to i64 -// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENTCAST]], 1 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: [[CASTED_ALIGN:%.*]] = zext i32 [[TMP0]] to i64 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -32,12 +28,8 @@ __INT32_TYPE__ test1(__INT32_TYPE__ a) { // CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[A_ADDR]], align 8 // CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP0]] to i32 // CHECK-NEXT: [[CALL:%.*]] = call i32* @m1(i32 [[CONV]]) -// CHECK-NEXT: [[ALIGNMENTCAST:%.*]] = zext i32 [[CONV]] to i64 -// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENTCAST]], 1 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: [[CASTED_ALIGN:%.*]] = zext i32 [[CONV]] to i64 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -55,11 +47,7 @@ __INT32_TYPE__ *m2(__SIZE_TYPE__ i) __attribute__((alloc_align(1))); // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_ADDR]], align 4 // CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 // CHECK-NEXT: [[CALL:%.*]] = call i32* @m2(i64 [[CONV]]) -// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[CONV]], 1 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CONV]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -75,11 +63,7 @@ __INT32_TYPE__ test3(__INT32_TYPE__ a) { // CHECK-NEXT: store i64 [[A]], i64* [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[A_ADDR]], align 8 // CHECK-NEXT: [[CALL:%.*]] = call i32* @m2(i64 [[TMP0]]) -// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[TMP0]], 1 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[TMP0]]) ] // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP1]] // @@ -115,12 +99,8 @@ __INT32_TYPE__ *m3(struct Empty s, __int128_t i) __attribute__((alloc_align(2))) // CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[TMP4]], i32 0, i32 1 // CHECK-NEXT: [[TMP8:%.*]] = load i64, i64* [[TMP7]], align 8 // CHECK-NEXT: [[CALL:%.*]] = call i32* @m3(i64 [[TMP6]], i64 [[TMP8]]) -// CHECK-NEXT: [[ALIGNMENTCAST:%.*]] = trunc i128 [[TMP3]] to i64 -// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENTCAST]], 1 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: [[CASTED_ALIGN:%.*]] = trunc i128 [[TMP3]] to i64 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP9]] // @@ -157,12 +137,8 @@ __INT32_TYPE__ *m4(struct MultiArgs s, __int128_t i) __attribute__((alloc_align( // CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds { i64, i64 }, { i64, i64 }* [[TMP9]], i32 0, i32 1 // CHECK-NEXT: [[TMP13:%.*]] = load i64, i64* [[TMP12]], align 8 // CHECK-NEXT: [[CALL:%.*]] = call i32* @m4(i64 [[TMP6]], i64 [[TMP8]], i64 [[TMP11]], i64 [[TMP13]]) -// CHECK-NEXT: [[ALIGNMENTCAST:%.*]] = trunc i128 [[TMP3]] to i64 -// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENTCAST]], 1 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: [[CASTED_ALIGN:%.*]] = trunc i128 [[TMP3]] to i64 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 [[CASTED_ALIGN]]) ] // CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP14]] // diff --git a/clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c b/clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c index fa4ee8db12e7f..cd8a6f19b4f49 100644 --- a/clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c +++ b/clang/test/CodeGen/assume-aligned-and-alloc-align-attributes.c @@ -36,12 +36,8 @@ void *t2_immediate2() { // CHECK-NEXT: store i32 [[ALIGNMENT:%.*]], i32* [[ALIGNMENT_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ALIGNMENT_ADDR]], align 4 // CHECK-NEXT: [[CALL:%.*]] = call align 32 i8* @my_aligned_alloc(i32 320, i32 [[TMP0]]) -// CHECK-NEXT: [[ALIGNMENTCAST:%.*]] = zext i32 [[TMP0]] to i64 -// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENTCAST]], 1 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[CALL]], i64 [[TMP1]]) ] // CHECK-NEXT: ret i8* [[CALL]] // void *t3_variable(int alignment) { diff --git a/clang/test/CodeGen/builtin-align-array.c b/clang/test/CodeGen/builtin-align-array.c index 97235c33b7fbe..31f7b42b56170 100644 --- a/clang/test/CodeGen/builtin-align-array.c +++ b/clang/test/CodeGen/builtin-align-array.c @@ -4,7 +4,7 @@ extern int func(char *c); -// CHECK-LABEL: define {{[^@]+}}@test_array() #0 +// CHECK-LABEL: @test_array( // CHECK-NEXT: entry: // CHECK-NEXT: [[BUF:%.*]] = alloca [1024 x i8], align 16 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BUF]], i64 0, i64 44 @@ -12,10 +12,7 @@ extern int func(char *c); // CHECK-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], -16 // CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]] // CHECK-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[ARRAYIDX]], i64 [[DIFF]] -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[ALIGNED_RESULT]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 15 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT]], i64 16) ] // CHECK-NEXT: [[CALL:%.*]] = call i32 @func(i8* [[ALIGNED_RESULT]]) // CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BUF]], i64 0, i64 22 // CHECK-NEXT: [[INTPTR2:%.*]] = ptrtoint i8* [[ARRAYIDX1]] to i64 @@ -23,13 +20,10 @@ extern int func(char *c); // CHECK-NEXT: [[ALIGNED_INTPTR4:%.*]] = and i64 [[OVER_BOUNDARY]], -32 // CHECK-NEXT: [[DIFF5:%.*]] = sub i64 [[ALIGNED_INTPTR4]], [[INTPTR2]] // CHECK-NEXT: [[ALIGNED_RESULT6:%.*]] = getelementptr inbounds i8, i8* [[ARRAYIDX1]], i64 [[DIFF5]] -// CHECK-NEXT: [[PTRINT7:%.*]] = ptrtoint i8* [[ALIGNED_RESULT6]] to i64 -// CHECK-NEXT: [[MASKEDPTR8:%.*]] = and i64 [[PTRINT7]], 31 -// CHECK-NEXT: [[MASKCOND9:%.*]] = icmp eq i64 [[MASKEDPTR8]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND9]]) -// CHECK-NEXT: [[CALL10:%.*]] = call i32 @func(i8* [[ALIGNED_RESULT6]]) -// CHECK-NEXT: [[ARRAYIDX11:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BUF]], i64 0, i64 16 -// CHECK-NEXT: [[SRC_ADDR:%.*]] = ptrtoint i8* [[ARRAYIDX11]] to i64 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT6]], i64 32) ] +// CHECK-NEXT: [[CALL7:%.*]] = call i32 @func(i8* [[ALIGNED_RESULT6]]) +// CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BUF]], i64 0, i64 16 +// CHECK-NEXT: [[SRC_ADDR:%.*]] = ptrtoint i8* [[ARRAYIDX8]] to i64 // CHECK-NEXT: [[SET_BITS:%.*]] = and i64 [[SRC_ADDR]], 63 // CHECK-NEXT: [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0 // CHECK-NEXT: [[CONV:%.*]] = zext i1 [[IS_ALIGNED]] to i32 @@ -42,7 +36,7 @@ int test_array(void) { return __builtin_is_aligned(&buf[16], 64); } -// CHECK-LABEL: define {{[^@]+}}@test_array_should_not_mask() #0 +// CHECK-LABEL: @test_array_should_not_mask( // CHECK-NEXT: entry: // CHECK-NEXT: [[BUF:%.*]] = alloca [1024 x i8], align 32 // CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BUF]], i64 0, i64 64 @@ -50,10 +44,7 @@ int test_array(void) { // CHECK-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], -16 // CHECK-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]] // CHECK-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[ARRAYIDX]], i64 [[DIFF]] -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[ALIGNED_RESULT]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 15 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT]], i64 16) ] // CHECK-NEXT: [[CALL:%.*]] = call i32 @func(i8* [[ALIGNED_RESULT]]) // CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], [1024 x i8]* [[BUF]], i64 0, i64 32 // CHECK-NEXT: [[INTPTR2:%.*]] = ptrtoint i8* [[ARRAYIDX1]] to i64 @@ -61,11 +52,8 @@ int test_array(void) { // CHECK-NEXT: [[ALIGNED_INTPTR4:%.*]] = and i64 [[OVER_BOUNDARY]], -32 // CHECK-NEXT: [[DIFF5:%.*]] = sub i64 [[ALIGNED_INTPTR4]], [[INTPTR2]] // CHECK-NEXT: [[ALIGNED_RESULT6:%.*]] = getelementptr inbounds i8, i8* [[ARRAYIDX1]], i64 [[DIFF5]] -// CHECK-NEXT: [[PTRINT7:%.*]] = ptrtoint i8* [[ALIGNED_RESULT6]] to i64 -// CHECK-NEXT: [[MASKEDPTR8:%.*]] = and i64 [[PTRINT7]], 31 -// CHECK-NEXT: [[MASKCOND9:%.*]] = icmp eq i64 [[MASKEDPTR8]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND9]]) -// CHECK-NEXT: [[CALL10:%.*]] = call i32 @func(i8* [[ALIGNED_RESULT6]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT6]], i64 32) ] +// CHECK-NEXT: [[CALL7:%.*]] = call i32 @func(i8* [[ALIGNED_RESULT6]]) // CHECK-NEXT: ret i32 1 // int test_array_should_not_mask(void) { diff --git a/clang/test/CodeGen/builtin-align.c b/clang/test/CodeGen/builtin-align.c index 7e66e2b5c0b9b..60f7fc99c1d4d 100644 --- a/clang/test/CodeGen/builtin-align.c +++ b/clang/test/CodeGen/builtin-align.c @@ -122,11 +122,7 @@ _Bool is_aligned(TYPE ptr, unsigned align) { // CHECK-VOID_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]] // CHECK-VOID_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]] // CHECK-VOID_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[DIFF]] -// CHECK-VOID_PTR-NEXT: [[MASK1:%.*]] = sub i64 [[ALIGNMENT]], 1 -// CHECK-VOID_PTR-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[ALIGNED_RESULT]] to i64 -// CHECK-VOID_PTR-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK1]] -// CHECK-VOID_PTR-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ] // CHECK-VOID_PTR-NEXT: ret i8* [[ALIGNED_RESULT]] // // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_up @@ -142,11 +138,7 @@ _Bool is_aligned(TYPE ptr, unsigned align) { // CHECK-FLOAT_PTR-NEXT: [[TMP0:%.*]] = bitcast float* [[PTR]] to i8* // CHECK-FLOAT_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 [[DIFF]] // CHECK-FLOAT_PTR-NEXT: [[TMP1:%.*]] = bitcast i8* [[ALIGNED_RESULT]] to float* -// CHECK-FLOAT_PTR-NEXT: [[MASK1:%.*]] = sub i64 [[ALIGNMENT]], 1 -// CHECK-FLOAT_PTR-NEXT: [[PTRINT:%.*]] = ptrtoint float* [[TMP1]] to i64 -// CHECK-FLOAT_PTR-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK1]] -// CHECK-FLOAT_PTR-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[TMP1]], i64 [[ALIGNMENT]]) ] // CHECK-FLOAT_PTR-NEXT: ret float* [[TMP1]] // // CHECK-LONG-LABEL: define {{[^@]+}}@align_up @@ -184,11 +176,7 @@ TYPE align_up(TYPE ptr, unsigned align) { // CHECK-VOID_PTR-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], [[INVERTED_MASK]] // CHECK-VOID_PTR-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[INTPTR]] // CHECK-VOID_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[DIFF]] -// CHECK-VOID_PTR-NEXT: [[MASK1:%.*]] = sub i64 [[ALIGNMENT]], 1 -// CHECK-VOID_PTR-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[ALIGNED_RESULT]] to i64 -// CHECK-VOID_PTR-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK1]] -// CHECK-VOID_PTR-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-VOID_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ] // CHECK-VOID_PTR-NEXT: ret i8* [[ALIGNED_RESULT]] // // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_down @@ -203,11 +191,7 @@ TYPE align_up(TYPE ptr, unsigned align) { // CHECK-FLOAT_PTR-NEXT: [[TMP0:%.*]] = bitcast float* [[PTR]] to i8* // CHECK-FLOAT_PTR-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 [[DIFF]] // CHECK-FLOAT_PTR-NEXT: [[TMP1:%.*]] = bitcast i8* [[ALIGNED_RESULT]] to float* -// CHECK-FLOAT_PTR-NEXT: [[MASK1:%.*]] = sub i64 [[ALIGNMENT]], 1 -// CHECK-FLOAT_PTR-NEXT: [[PTRINT:%.*]] = ptrtoint float* [[TMP1]] to i64 -// CHECK-FLOAT_PTR-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK1]] -// CHECK-FLOAT_PTR-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-FLOAT_PTR-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[TMP1]], i64 [[ALIGNMENT]]) ] // CHECK-FLOAT_PTR-NEXT: ret float* [[TMP1]] // // CHECK-LONG-LABEL: define {{[^@]+}}@align_down diff --git a/clang/test/CodeGen/builtin-assume-aligned.c b/clang/test/CodeGen/builtin-assume-aligned.c index 90693cc215200..b9f1ebfbdcf58 100644 --- a/clang/test/CodeGen/builtin-assume-aligned.c +++ b/clang/test/CodeGen/builtin-assume-aligned.c @@ -8,10 +8,7 @@ // CHECK-NEXT: store i32* [[A]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[TMP1]], i64 32, i64 0) ] // CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* // CHECK-NEXT: store i32* [[TMP2]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load i32*, i32** [[A_ADDR]], align 8 @@ -31,10 +28,7 @@ int test1(int *a) { // CHECK-NEXT: store i32* [[A]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[TMP1]], i64 32, i64 0) ] // CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* // CHECK-NEXT: store i32* [[TMP2]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load i32*, i32** [[A_ADDR]], align 8 @@ -54,10 +48,7 @@ int test2(int *a) { // CHECK-NEXT: store i32* [[A]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[TMP1]], i64 32) ] // CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* // CHECK-NEXT: store i32* [[TMP2]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load i32*, i32** [[A_ADDR]], align 8 @@ -81,11 +72,7 @@ int test3(int *a) { // CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* // CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[B_ADDR]], align 4 // CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP2]] to i64 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[TMP1]] to i64 -// CHECK-NEXT: [[OFFSETPTR:%.*]] = sub i64 [[PTRINT]], [[CONV]] -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[OFFSETPTR]], 31 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[TMP1]], i64 32, i64 [[CONV]]) ] // CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP1]] to i32* // CHECK-NEXT: store i32* [[TMP3]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP4:%.*]] = load i32*, i32** [[A_ADDR]], align 8 @@ -115,11 +102,7 @@ int *m2() __attribute__((assume_aligned(64, 12))); // CHECK-LABEL: define {{[^@]+}}@test6() #0 // CHECK-NEXT: entry: // CHECK-NEXT: [[CALL:%.*]] = call i32* (...) @m2() -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[CALL]] to i64 -// CHECK-NEXT: [[OFFSETPTR:%.*]] = sub i64 [[PTRINT]], 12 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[OFFSETPTR]], 63 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[CALL]], i64 64, i64 12) ] // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[CALL]], align 4 // CHECK-NEXT: ret i32 [[TMP0]] // @@ -134,10 +117,7 @@ int test6() { // CHECK-NEXT: store i32* [[A]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to i8* -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[TMP1]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 536870911 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[TMP1]], i64 536870912) ] // CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* // CHECK-NEXT: store i32* [[TMP2]], i32** [[A_ADDR]], align 8 // CHECK-NEXT: [[TMP3:%.*]] = load i32*, i32** [[A_ADDR]], align 8 diff --git a/clang/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-lvalue.cpp b/clang/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-lvalue.cpp index 96d264190bec7..fb2b1a76116e9 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-lvalue.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-lvalue.cpp @@ -21,9 +21,9 @@ char **load_from_ac_struct(struct ac_struct *x) { // CHECK-NEXT: %[[X_RELOADED:.*]] = load %[[STRUCT_AC_STRUCT]]*, %[[STRUCT_AC_STRUCT]]** %[[STRUCT_AC_STRUCT_ADDR]], align 8 // CHECK: %[[A_ADDR:.*]] = getelementptr inbounds %[[STRUCT_AC_STRUCT]], %[[STRUCT_AC_STRUCT]]* %[[X_RELOADED]], i32 0, i32 0 // CHECK: %[[A:.*]] = load i8**, i8*** %[[A_ADDR]], align 8 - // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[A]] to i64 - // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 2147483647 - // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 + // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[A]] to i64 + // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 2147483647 + // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[A]] to i64, !nosanitize // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]: @@ -32,7 +32,7 @@ char **load_from_ac_struct(struct ac_struct *x) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8** %[[A]], i64 2147483648) ] // CHECK-NEXT: ret i8** %[[A]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-paramvar.cpp b/clang/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-paramvar.cpp index 0e3fa750c66c3..46f7d09ae2aa5 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-paramvar.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-attribute-align_value-on-paramvar.cpp @@ -24,7 +24,7 @@ char **passthrough(__attribute__((align_value(0x80000000))) char **x) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-SANITIZE-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-SANITIZE-NEXT: call void @llvm.assume(i1 true) [ "align"(i8** %[[X_RELOADED]], i64 2147483648) ] // CHECK-NEXT: ret i8** %[[X_RELOADED]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp b/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp index 591eaa0e13131..40abbc3871996 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function-variable.cpp @@ -30,10 +30,10 @@ char **caller(char **x, unsigned long alignment) { // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[ALIGNMENT_RELOADED:.*]] = load i64, i64* %[[ALIGNMENT_ADDR]], align 8 // CHECK-NEXT: %[[X_RETURNED:.*]] = call i8** @[[PASSTHROUGH]](i8** %[[X_RELOADED]], i64 %[[ALIGNMENT_RELOADED]]) - // CHECK-NEXT: %[[MASK:.*]] = sub i64 %[[ALIGNMENT_RELOADED]], 1 - // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64 - // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], %[[MASK]] - // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 + // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64 + // CHECK-SANITIZE-NEXT: %[[MASK:.*]] = sub i64 %[[ALIGNMENT_RELOADED]], 1 + // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], %[[MASK]] + // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64, !nosanitize // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]: @@ -42,7 +42,7 @@ char **caller(char **x, unsigned long alignment) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8** %[[X_RETURNED]], i64 %1) ] // CHECK-NEXT: ret i8** %[[X_RETURNED]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp b/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp index a41357933f918..87d903c69716c 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-attribute-alloc_align-on-function.cpp @@ -39,7 +39,7 @@ char **caller(char **x) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-SANITIZE-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-SANITIZE-NEXT: call void @llvm.assume(i1 true) [ "align"(i8** %[[X_RETURNED]], i64 128) ] // CHECK-NEXT: ret i8** %[[X_RETURNED]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp b/clang/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp index e78667ce16e06..ecc96bcf6a53b 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function-two-params.cpp @@ -24,10 +24,10 @@ char **caller(char **x) { // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[X_RETURNED:.*]] = call i8** @[[PASSTHROUGH]](i8** %[[X_RELOADED]]) - // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64 - // CHECK-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], 42 - // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 2147483647 - // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 + // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64 + // CHECK-SANITIZE-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], 42 + // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 2147483647 + // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8** %[[X_RETURNED]] to i64, !nosanitize // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]: @@ -36,7 +36,7 @@ char **caller(char **x) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8** %[[X_RETURNED]], i64 2147483648, i64 42) ] // CHECK-NEXT: ret i8** %[[X_RETURNED]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function.cpp b/clang/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function.cpp index f750bbd77d42f..5bbc5843b89f8 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-attribute-assume_aligned-on-function.cpp @@ -36,7 +36,7 @@ char **caller(char **x) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-SANITIZE-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-SANITIZE-NEXT: call void @llvm.assume(i1 true) [ "align"(i8** %[[X_RETURNED]], i64 128) ] // CHECK-NEXT: ret i8** %[[X_RETURNED]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params-variable.cpp b/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params-variable.cpp index 4306e322f5fb6..9c8944ba280b4 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params-variable.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params-variable.cpp @@ -16,10 +16,10 @@ void *caller(char **x, unsigned long offset) { // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[BITCAST:.*]] = bitcast i8** %[[X_RELOADED]] to i8* // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, i64* %[[OFFSET_ADDR]], align 8 - // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64 - // CHECK-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], %[[OFFSET_RELOADED]] - // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 536870911 - // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 + // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64 + // CHECK-SANITIZE-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], %[[OFFSET_RELOADED]] + // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 536870911 + // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[BITCAST]] to i64, !nosanitize // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]: @@ -28,7 +28,7 @@ void *caller(char **x, unsigned long offset) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* %[[BITCAST]], i64 536870912, i64 %[[OFFSET_RELOADED]]) ] // CHECK-NEXT: ret i8* %[[BITCAST]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params.cpp b/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params.cpp index 27f53e92bed89..9f61e08106a01 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-three-params.cpp @@ -13,10 +13,10 @@ void *caller(char **x) { // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[BITCAST:.*]] = bitcast i8** %[[X_RELOADED]] to i8* - // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64 - // CHECK-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], 42 - // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 536870911 - // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 + // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64 + // CHECK-SANITIZE-NEXT: %[[OFFSETPTR:.*]] = sub i64 %[[PTRINT]], 42 + // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[OFFSETPTR]], 536870911 + // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[BITCAST]] to i64, !nosanitize // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]: @@ -25,7 +25,7 @@ void *caller(char **x) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* %[[BITCAST]], i64 536870912, i64 42) ] // CHECK-NEXT: ret i8* %[[BITCAST]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-two-params.cpp b/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-two-params.cpp index 5412270f37619..20bed646ff951 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-two-params.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-builtin_assume_aligned-two-params.cpp @@ -13,9 +13,9 @@ void *caller(char **x) { // CHECK-NEXT: store i8** %[[X]], i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[X_RELOADED:.*]] = load i8**, i8*** %[[X_ADDR]], align 8 // CHECK-NEXT: %[[BITCAST:.*]] = bitcast i8** %[[X_RELOADED]] to i8* - // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64 - // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 536870911 - // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 + // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[BITCAST]] to i64 + // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 536870911 + // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[BITCAST]] to i64, !nosanitize // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]: @@ -24,7 +24,7 @@ void *caller(char **x) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* %[[BITCAST]], i64 536870912) ] // CHECK-NEXT: ret i8* %[[BITCAST]] // CHECK-NEXT: } #line 100 diff --git a/clang/test/CodeGen/catch-alignment-assumption-openmp.cpp b/clang/test/CodeGen/catch-alignment-assumption-openmp.cpp index 6d75ee0858dac..353f2fd7f17bd 100644 --- a/clang/test/CodeGen/catch-alignment-assumption-openmp.cpp +++ b/clang/test/CodeGen/catch-alignment-assumption-openmp.cpp @@ -12,9 +12,9 @@ void func(char *data) { // CHECK-NEXT: %[[DATA_ADDR:.*]] = alloca i8*, align 8 // CHECK: store i8* %[[DATA]], i8** %[[DATA_ADDR]], align 8 // CHECK: %[[DATA_RELOADED:.*]] = load i8*, i8** %[[DATA_ADDR]], align 8 - // CHECK-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[DATA_RELOADED]] to i64 - // CHECK-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 1073741823 - // CHECK-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 + // CHECK-SANITIZE-NEXT: %[[PTRINT:.*]] = ptrtoint i8* %[[DATA_RELOADED]] to i64 + // CHECK-SANITIZE-NEXT: %[[MASKEDPTR:.*]] = and i64 %[[PTRINT]], 1073741823 + // CHECK-SANITIZE-NEXT: %[[MASKCOND:.*]] = icmp eq i64 %[[MASKEDPTR]], 0 // CHECK-SANITIZE-NEXT: %[[PTRINT_DUP:.*]] = ptrtoint i8* %[[DATA_RELOADED]] to i64, !nosanitize // CHECK-SANITIZE-NEXT: br i1 %[[MASKCOND]], label %[[CONT:.*]], label %[[HANDLER_ALIGNMENT_ASSUMPTION:[^,]+]],{{.*}} !nosanitize // CHECK-SANITIZE: [[HANDLER_ALIGNMENT_ASSUMPTION]]: @@ -23,7 +23,7 @@ void func(char *data) { // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.trap(){{.*}}, !nosanitize // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize // CHECK-SANITIZE: [[CONT]]: - // CHECK-NEXT: call void @llvm.assume(i1 %[[MASKCOND]]) + // CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* %[[DATA_RELOADED]], i64 1073741824) ] #line 100 #pragma omp for simd aligned(data : 0x40000000) diff --git a/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c b/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c index 9467f6228dfc4..b8ce1699f7ed0 100644 --- a/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c +++ b/clang/test/CodeGen/non-power-of-2-alignment-assumptions.c @@ -9,12 +9,8 @@ void *__attribute__((alloc_align(1))) alloc(int align); // CHECK-NEXT: store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ALIGN_ADDR]], align 4 // CHECK-NEXT: [[CALL:%.*]] = call i8* @alloc(i32 [[TMP0]]) -// CHECK-NEXT: [[ALIGNMENTCAST:%.*]] = zext i32 [[TMP0]] to i64 -// CHECK-NEXT: [[MASK:%.*]] = sub i64 [[ALIGNMENTCAST]], 1 -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], [[MASK]] -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[CALL]], i64 [[TMP1]]) ] // CHECK-NEXT: ret void // void t0(int align) { @@ -25,10 +21,7 @@ void t0(int align) { // CHECK-NEXT: [[ALIGN_ADDR:%.*]] = alloca i32, align 4 // CHECK-NEXT: store i32 [[ALIGN:%.*]], i32* [[ALIGN_ADDR]], align 4 // CHECK-NEXT: [[CALL:%.*]] = call i8* @alloc(i32 7) -// CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i8* [[CALL]] to i64 -// CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 6 -// CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[CALL]], i64 7) ] // CHECK-NEXT: ret void // void t1(int align) { diff --git a/clang/test/OpenMP/simd_codegen.cpp b/clang/test/OpenMP/simd_codegen.cpp index cb53bb1aa38b8..3440225673c4d 100644 --- a/clang/test/OpenMP/simd_codegen.cpp +++ b/clang/test/OpenMP/simd_codegen.cpp @@ -817,25 +817,9 @@ void parallel_simd(float *a) { // TERM_DEBUG: !{{[0-9]+}} = !DILocation(line: [[@LINE-11]], // CHECK-LABEL: S8 -// CHECK-DAG: ptrtoint [[SS_TY]]* %{{.+}} to i64 -// CHECK-DAG: ptrtoint [[SS_TY]]* %{{.+}} to i64 -// CHECK-DAG: ptrtoint [[SS_TY]]* %{{.+}} to i64 -// CHECK-DAG: ptrtoint [[SS_TY]]* %{{.+}} to i64 - -// CHECK-DAG: and i64 %{{.+}}, 15 -// CHECK-DAG: icmp eq i64 %{{.+}}, 0 // CHECK-DAG: call void @llvm.assume(i1 - -// CHECK-DAG: and i64 %{{.+}}, 7 -// CHECK-DAG: icmp eq i64 %{{.+}}, 0 // CHECK-DAG: call void @llvm.assume(i1 - -// CHECK-DAG: and i64 %{{.+}}, 15 -// CHECK-DAG: icmp eq i64 %{{.+}}, 0 // CHECK-DAG: call void @llvm.assume(i1 - -// CHECK-DAG: and i64 %{{.+}}, 3 -// CHECK-DAG: icmp eq i64 %{{.+}}, 0 // CHECK-DAG: call void @llvm.assume(i1 struct SS { SS(): a(0) {} diff --git a/clang/test/OpenMP/simd_metadata.c b/clang/test/OpenMP/simd_metadata.c index f0ae0200dd08e..18133e3b6c2e7 100644 --- a/clang/test/OpenMP/simd_metadata.c +++ b/clang/test/OpenMP/simd_metadata.c @@ -21,30 +21,21 @@ void h1(float *c, float *a, double b[], int size) // CHECK-LABEL: define void @h1 int t = 0; #pragma omp simd safelen(16) linear(t) aligned(c:32) aligned(a,b) -// CHECK: [[C_PTRINT:%.+]] = ptrtoint -// CHECK-NEXT: [[C_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[C_PTRINT]], 31 -// CHECK-NEXT: [[C_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[C_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[C_MASKCOND]]) -// CHECK: [[A_PTRINT:%.+]] = ptrtoint - -// X86-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 -// X86-AVX-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 31 -// X86-AVX512-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 63 -// PPC-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 -// PPC-QPX-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 - -// CHECK-NEXT: [[A_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[A_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[A_MASKCOND]]) -// CHECK: [[B_PTRINT:%.+]] = ptrtoint - -// X86-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 15 -// X86-AVX-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 31 -// X86-AVX512-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 63 -// PPC-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 15 -// PPC-QPX-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 31 - -// CHECK-NEXT: [[B_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[B_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[B_MASKCOND]]) + // CHECK: call void @llvm.assume(i1 true) [ "align"(float* [[PTR4:%.*]], {{i64|i32}} 32) ] + // CHECK-NEXT: load + + // X86-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // X86-AVX-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 32) ] + // X86-AVX512-NEXT:call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 64) ] + // PPC-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // PPC-QPX-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // CHECK-NEXT: load + + // X86-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 16) ] + // X86-AVX-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 32) ] + // X86-AVX512-NEXT:call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 64) ] + // PPC-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 16) ] + // PPC-QPX-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 32) ] for (int i = 0; i < size; ++i) { c[i] = a[i] * a[i] + b[i] * b[t]; ++t; @@ -52,30 +43,21 @@ void h1(float *c, float *a, double b[], int size) // do not emit llvm.access.group metadata due to usage of safelen clause. // CHECK-NOT: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.access.group {{![0-9]+}} #pragma omp simd safelen(16) linear(t) aligned(c:32) aligned(a,b) simdlen(8) -// CHECK: [[C_PTRINT:%.+]] = ptrtoint -// CHECK-NEXT: [[C_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[C_PTRINT]], 31 -// CHECK-NEXT: [[C_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[C_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[C_MASKCOND]]) -// CHECK: [[A_PTRINT:%.+]] = ptrtoint - -// X86-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 -// X86-AVX-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 31 -// X86-AVX512-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 63 -// PPC-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 -// PPC-QPX-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 - -// CHECK-NEXT: [[A_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[A_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[A_MASKCOND]]) -// CHECK: [[B_PTRINT:%.+]] = ptrtoint - -// X86-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 15 -// X86-AVX-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 31 -// X86-AVX512-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 63 -// PPC-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 15 -// PPC-QPX-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 31 - -// CHECK-NEXT: [[B_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[B_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[B_MASKCOND]]) + // CHECK: call void @llvm.assume(i1 true) [ "align"(float* [[PTR4:%.*]], {{i64|i32}} 32) ] + // CHECK-NEXT: load + + // X86-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // X86-AVX-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 32) ] + // X86-AVX512-NEXT:call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 64) ] + // PPC-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // PPC-QPX-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // CHECK-NEXT: load + + // X86-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 16) ] + // X86-AVX-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 32) ] + // X86-AVX512-NEXT:call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 64) ] + // PPC-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 16) ] + // PPC-QPX-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 32) ] for (int i = 0; i < size; ++i) { c[i] = a[i] * a[i] + b[i] * b[t]; ++t; @@ -83,30 +65,21 @@ void h1(float *c, float *a, double b[], int size) // do not emit llvm.access.group metadata due to usage of safelen clause. // CHECK-NOT: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.access.group {{![0-9]+}} #pragma omp simd linear(t) aligned(c:32) aligned(a,b) simdlen(8) -// CHECK: [[C_PTRINT:%.+]] = ptrtoint -// CHECK-NEXT: [[C_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[C_PTRINT]], 31 -// CHECK-NEXT: [[C_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[C_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[C_MASKCOND]]) -// CHECK: [[A_PTRINT:%.+]] = ptrtoint - -// X86-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 -// X86-AVX-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 31 -// X86-AVX512-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 63 -// PPC-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 -// PPC-QPX-NEXT: [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15 - -// CHECK-NEXT: [[A_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[A_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[A_MASKCOND]]) -// CHECK: [[B_PTRINT:%.+]] = ptrtoint - -// X86-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 15 -// X86-AVX-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 31 -// X86-AVX512-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 63 -// PPC-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 15 -// PPC-QPX-NEXT: [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 31 - -// CHECK-NEXT: [[B_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[B_MASKEDPTR]], 0 -// CHECK-NEXT: call void @llvm.assume(i1 [[B_MASKCOND]]) + // CHECK: call void @llvm.assume(i1 true) [ "align"(float* [[PTR4:%.*]], {{i64|i32}} 32) ] + // CHECK-NEXT: load + + // X86-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // X86-AVX-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 32) ] + // X86-AVX512-NEXT:call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 64) ] + // PPC-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // PPC-QPX-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[PTR5:%.*]], {{i64|i32}} 16) ] + // CHECK-NEXT: load + + // X86-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 16) ] + // X86-AVX-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 32) ] + // X86-AVX512-NEXT:call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 64) ] + // PPC-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 16) ] + // PPC-QPX-NEXT: call void @llvm.assume(i1 true) [ "align"(double* [[PTR6:%.*]], {{i64|i32}} 32) ] for (int i = 0; i < size; ++i) { c[i] = a[i] * a[i] + b[i] * b[t]; ++t; diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp index 2fc166ed0b873..7192ef454d0a5 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp @@ -101,10 +101,7 @@ int target_teams_fun(int *g){ // CK1: define internal void @[[OUTL1]]({{.+}}) // CK1: [[ARRDECAY:%.+]] = getelementptr inbounds [1000 x i32], [1000 x i32]* %{{.+}}, i{{32|64}} 0, i{{32|64}} 0 - // CK1: [[ARR_CAST:%.+]] = ptrtoint i32* [[ARRDECAY]] to i{{32|64}} - // CK1: [[MASKED_PTR:%.+]] = and i{{32|64}} [[ARR_CAST]], 7 - // CK1: [[COND:%.+]] = icmp eq i{{32|64}} [[MASKED_PTR]], 0 - // CK1: call void @llvm.assume(i1 [[COND]]) + // CK1: call void @llvm.assume(i1 true) [ "align"(i32* [[ARRDECAY]], {{i64|i32}} 8) ] // CK1: call void @__kmpc_for_static_init_4( // CK1: call void {{.+}} @__kmpc_fork_call( // CK1: call void @__kmpc_for_static_fini( diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index ffec4ff64ca66..4552ca016bd76 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -782,7 +782,11 @@ class IRBuilderBase { /// Create an assume intrinsic call that allows the optimizer to /// assume that the provided condition will be true. - CallInst *CreateAssumption(Value *Cond); + /// + /// The optional argument \p OpBundles specifies operand bundles that are + /// added to the call instruction. + CallInst *CreateAssumption(Value *Cond, + ArrayRef OpBundles = llvm::None); /// Create a call to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. @@ -2502,13 +2506,11 @@ class IRBuilderBase { private: /// Helper function that creates an assume intrinsic call that - /// represents an alignment assumption on the provided Ptr, Mask, Type - /// and Offset. It may be sometimes useful to do some other logic - /// based on this alignment check, thus it can be stored into 'TheCheck'. + /// represents an alignment assumption on the provided pointer \p PtrValue + /// with offset \p OffsetValue and alignment value \p AlignValue. CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL, - Value *PtrValue, Value *Mask, - Type *IntPtrTy, Value *OffsetValue, - Value **TheCheck); + Value *PtrValue, Value *AlignValue, + Value *OffsetValue); public: /// Create an assume intrinsic call that represents an alignment @@ -2517,13 +2519,9 @@ class IRBuilderBase { /// An optional offset can be provided, and if it is provided, the offset /// must be subtracted from the provided pointer to get the pointer with the /// specified alignment. - /// - /// It may be sometimes useful to do some other logic - /// based on this alignment check, thus it can be stored into 'TheCheck'. CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, unsigned Alignment, - Value *OffsetValue = nullptr, - Value **TheCheck = nullptr); + Value *OffsetValue = nullptr); /// Create an assume intrinsic call that represents an alignment /// assumption on the provided pointer. @@ -2532,15 +2530,11 @@ class IRBuilderBase { /// must be subtracted from the provided pointer to get the pointer with the /// specified alignment. /// - /// It may be sometimes useful to do some other logic - /// based on this alignment check, thus it can be stored into 'TheCheck'. - /// /// This overload handles the condition where the Alignment is dependent /// on an existing value rather than a static value. CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, Value *Alignment, - Value *OffsetValue = nullptr, - Value **TheCheck = nullptr); + Value *OffsetValue = nullptr); }; /// This provides a uniform API for creating instructions and inserting diff --git a/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h b/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h index be119b8ab8552..10b6e1c6a21b6 100644 --- a/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h +++ b/llvm/include/llvm/Transforms/Scalar/AlignmentFromAssumptions.h @@ -37,9 +37,9 @@ struct AlignmentFromAssumptionsPass ScalarEvolution *SE = nullptr; DominatorTree *DT = nullptr; - bool extractAlignmentInfo(CallInst *I, Value *&AAPtr, const SCEV *&AlignSCEV, - const SCEV *&OffSCEV); - bool processAssumption(CallInst *I); + bool extractAlignmentInfo(CallInst *I, unsigned Idx, Value *&AAPtr, + const SCEV *&AlignSCEV, const SCEV *&OffSCEV); + bool processAssumption(CallInst *I, unsigned Idx); }; } diff --git a/llvm/lib/Analysis/AssumeBundleQueries.cpp b/llvm/lib/Analysis/AssumeBundleQueries.cpp index e9da1e607b45b..af81216f65264 100644 --- a/llvm/lib/Analysis/AssumeBundleQueries.cpp +++ b/llvm/lib/Analysis/AssumeBundleQueries.cpp @@ -96,10 +96,17 @@ llvm::getKnowledgeFromBundle(CallInst &Assume, Result.AttrKind = Attribute::getAttrKindFromName(BOI.Tag->getKey()); if (bundleHasArgument(BOI, ABA_WasOn)) Result.WasOn = getValueFromBundleOpInfo(Assume, BOI, ABA_WasOn); + auto GetArgOr1 = [&](unsigned Idx) -> unsigned { + if (auto *ConstInt = dyn_cast( + getValueFromBundleOpInfo(Assume, BOI, ABA_Argument + Idx))) + return ConstInt->getZExtValue(); + return 1; + }; if (BOI.End - BOI.Begin > ABA_Argument) - Result.ArgValue = - cast(getValueFromBundleOpInfo(Assume, BOI, ABA_Argument)) - ->getZExtValue(); + Result.ArgValue = GetArgOr1(0); + if (Result.AttrKind == Attribute::Alignment) + if (BOI.End - BOI.Begin > ABA_Argument + 1) + Result.ArgValue = MinAlign(Result.ArgValue, GetArgOr1(1)); return Result; } diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 1fffce015f707..b87dfe1c8df65 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -71,8 +71,9 @@ Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) { static CallInst *createCallHelper(Function *Callee, ArrayRef Ops, IRBuilderBase *Builder, const Twine &Name = "", - Instruction *FMFSource = nullptr) { - CallInst *CI = Builder->CreateCall(Callee, Ops, Name); + Instruction *FMFSource = nullptr, + ArrayRef OpBundles = {}) { + CallInst *CI = Builder->CreateCall(Callee, Ops, OpBundles, Name); if (FMFSource) CI->copyFastMathFlags(FMFSource); return CI; @@ -449,14 +450,16 @@ CallInst *IRBuilderBase::CreateInvariantStart(Value *Ptr, ConstantInt *Size) { return createCallHelper(TheFn, Ops, this); } -CallInst *IRBuilderBase::CreateAssumption(Value *Cond) { +CallInst * +IRBuilderBase::CreateAssumption(Value *Cond, + ArrayRef OpBundles) { assert(Cond->getType() == getInt1Ty() && "an assumption condition must be of type i1"); Value *Ops[] = { Cond }; Module *M = BB->getParent()->getParent(); Function *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume); - return createCallHelper(FnAssume, Ops, this); + return createCallHelper(FnAssume, Ops, this, "", nullptr, OpBundles); } /// Create a call to a Masked Load intrinsic. @@ -1107,63 +1110,37 @@ Value *IRBuilderBase::CreatePreserveStructAccessIndex( return Fn; } -CallInst *IRBuilderBase::CreateAlignmentAssumptionHelper( - const DataLayout &DL, Value *PtrValue, Value *Mask, Type *IntPtrTy, - Value *OffsetValue, Value **TheCheck) { - Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); - - if (OffsetValue) { - bool IsOffsetZero = false; - if (const auto *CI = dyn_cast(OffsetValue)) - IsOffsetZero = CI->isZero(); - - if (!IsOffsetZero) { - if (OffsetValue->getType() != IntPtrTy) - OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true, - "offsetcast"); - PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr"); - } - } - - Value *Zero = ConstantInt::get(IntPtrTy, 0); - Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr"); - Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond"); - if (TheCheck) - *TheCheck = InvCond; - - return CreateAssumption(InvCond); +CallInst *IRBuilderBase::CreateAlignmentAssumptionHelper(const DataLayout &DL, + Value *PtrValue, + Value *AlignValue, + Value *OffsetValue) { + SmallVector Vals({PtrValue, AlignValue}); + if (OffsetValue) + Vals.push_back(OffsetValue); + OperandBundleDefT AlignOpB("align", Vals); + return CreateAssumption(ConstantInt::getTrue(getContext()), {AlignOpB}); } -CallInst *IRBuilderBase::CreateAlignmentAssumption( - const DataLayout &DL, Value *PtrValue, unsigned Alignment, - Value *OffsetValue, Value **TheCheck) { +CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL, + Value *PtrValue, + unsigned Alignment, + Value *OffsetValue) { assert(isa(PtrValue->getType()) && "trying to create an alignment assumption on a non-pointer?"); assert(Alignment != 0 && "Invalid Alignment"); auto *PtrTy = cast(PtrValue->getType()); Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); - - Value *Mask = ConstantInt::get(IntPtrTy, Alignment - 1); - return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, - OffsetValue, TheCheck); + Value *AlignValue = ConstantInt::get(IntPtrTy, Alignment); + return CreateAlignmentAssumptionHelper(DL, PtrValue, AlignValue, OffsetValue); } -CallInst *IRBuilderBase::CreateAlignmentAssumption( - const DataLayout &DL, Value *PtrValue, Value *Alignment, - Value *OffsetValue, Value **TheCheck) { +CallInst *IRBuilderBase::CreateAlignmentAssumption(const DataLayout &DL, + Value *PtrValue, + Value *Alignment, + Value *OffsetValue) { assert(isa(PtrValue->getType()) && "trying to create an alignment assumption on a non-pointer?"); - auto *PtrTy = cast(PtrValue->getType()); - Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); - - if (Alignment->getType() != IntPtrTy) - Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ false, - "alignmentcast"); - - Value *Mask = CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "mask"); - - return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, - OffsetValue, TheCheck); + return CreateAlignmentAssumptionHelper(DL, PtrValue, Alignment, OffsetValue); } IRBuilderDefaultInserter::~IRBuilderDefaultInserter() {} diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 8fa87b7489013..3c8e73a03cc59 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -4449,21 +4449,32 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { Assert(Elem.Tag->getKey() == "ignore" || Attribute::isExistingAttribute(Elem.Tag->getKey()), "tags must be valid attribute names"); - Assert(Elem.End - Elem.Begin <= 2, "to many arguments"); Attribute::AttrKind Kind = Attribute::getAttrKindFromName(Elem.Tag->getKey()); + unsigned ArgCount = Elem.End - Elem.Begin; + if (Kind == Attribute::Alignment) { + Assert(ArgCount <= 3 && ArgCount >= 2, + "alignment assumptions should have 2 or 3 arguments"); + Assert(Call.getOperand(Elem.Begin)->getType()->isPointerTy(), + "first argument should be a pointer"); + Assert(Call.getOperand(Elem.Begin + 1)->getType()->isIntegerTy(), + "second argument should be an integer"); + if (ArgCount == 3) + Assert(Call.getOperand(Elem.Begin + 2)->getType()->isIntegerTy(), + "third argument should be an integer if present"); + return; + } + Assert(ArgCount <= 2, "to many arguments"); if (Kind == Attribute::None) break; if (Attribute::doesAttrKindHaveArgument(Kind)) { - Assert(Elem.End - Elem.Begin == 2, - "this attribute should have 2 arguments"); + Assert(ArgCount == 2, "this attribute should have 2 arguments"); Assert(isa(Call.getOperand(Elem.Begin + 1)), "the second argument should be a constant integral value"); } else if (isFuncOnlyAttr(Kind)) { - Assert((Elem.End - Elem.Begin) == 0, "this attribute has no argument"); + Assert((ArgCount) == 0, "this attribute has no argument"); } else if (!isFuncOrArgAttr(Kind)) { - Assert((Elem.End - Elem.Begin) == 1, - "this attribute should have one argument"); + Assert((ArgCount) == 1, "this attribute should have one argument"); } } break; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 836af6234ad5c..c734c9a68fb2d 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -4220,11 +4220,16 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { break; case Intrinsic::assume: { Value *IIOperand = II->getArgOperand(0); + SmallVector OpBundles; + II->getOperandBundlesAsDefs(OpBundles); + bool HasOpBundles = !OpBundles.empty(); // Remove an assume if it is followed by an identical assume. // TODO: Do we need this? Unless there are conflicting assumptions, the // computeKnownBits(IIOperand) below here eliminates redundant assumes. Instruction *Next = II->getNextNonDebugInstruction(); - if (match(Next, m_Intrinsic(m_Specific(IIOperand)))) + if (HasOpBundles && + match(Next, m_Intrinsic(m_Specific(IIOperand))) && + !cast(Next)->hasOperandBundles()) return eraseInstFromFunction(CI); // Canonicalize assume(a && b) -> assume(a); assume(b); @@ -4234,14 +4239,15 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { Value *AssumeIntrinsic = II->getCalledOperand(); Value *A, *B; if (match(IIOperand, m_And(m_Value(A), m_Value(B)))) { - Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, A, II->getName()); + Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, A, OpBundles, + II->getName()); Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, B, II->getName()); return eraseInstFromFunction(*II); } // assume(!(a || b)) -> assume(!a); assume(!b); if (match(IIOperand, m_Not(m_Or(m_Value(A), m_Value(B))))) { Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, - Builder.CreateNot(A), II->getName()); + Builder.CreateNot(A), OpBundles, II->getName()); Builder.CreateCall(AssumeIntrinsicTy, AssumeIntrinsic, Builder.CreateNot(B), II->getName()); return eraseInstFromFunction(*II); @@ -4257,7 +4263,8 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { isValidAssumeForContext(II, LHS, &DT)) { MDNode *MD = MDNode::get(II->getContext(), None); LHS->setMetadata(LLVMContext::MD_nonnull, MD); - return eraseInstFromFunction(*II); + if (!HasOpBundles) + return eraseInstFromFunction(*II); // TODO: apply nonnull return attributes to calls and invokes // TODO: apply range metadata for range check patterns? diff --git a/llvm/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp b/llvm/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp index 5c008585869cd..bccf94fc217fe 100644 --- a/llvm/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp +++ b/llvm/lib/Transforms/Scalar/AlignmentFromAssumptions.cpp @@ -15,6 +15,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/IR/Instructions.h" #include "llvm/InitializePasses.h" #define AA_NAME "alignment-from-assumptions" #define DEBUG_TYPE AA_NAME @@ -203,103 +204,33 @@ static Align getNewAlignment(const SCEV *AASCEV, const SCEV *AlignSCEV, } bool AlignmentFromAssumptionsPass::extractAlignmentInfo(CallInst *I, + unsigned Idx, Value *&AAPtr, const SCEV *&AlignSCEV, const SCEV *&OffSCEV) { - // An alignment assume must be a statement about the least-significant - // bits of the pointer being zero, possibly with some offset. - ICmpInst *ICI = dyn_cast(I->getArgOperand(0)); - if (!ICI) + Type *Int64Ty = Type::getInt64Ty(I->getContext()); + OperandBundleUse AlignOB = I->getOperandBundleAt(Idx); + if (AlignOB.getTagName() != "align") return false; - - // This must be an expression of the form: x & m == 0. - if (ICI->getPredicate() != ICmpInst::ICMP_EQ) - return false; - - // Swap things around so that the RHS is 0. - Value *CmpLHS = ICI->getOperand(0); - Value *CmpRHS = ICI->getOperand(1); - const SCEV *CmpLHSSCEV = SE->getSCEV(CmpLHS); - const SCEV *CmpRHSSCEV = SE->getSCEV(CmpRHS); - if (CmpLHSSCEV->isZero()) - std::swap(CmpLHS, CmpRHS); - else if (!CmpRHSSCEV->isZero()) - return false; - - BinaryOperator *CmpBO = dyn_cast(CmpLHS); - if (!CmpBO || CmpBO->getOpcode() != Instruction::And) - return false; - - // Swap things around so that the right operand of the and is a constant - // (the mask); we cannot deal with variable masks. - Value *AndLHS = CmpBO->getOperand(0); - Value *AndRHS = CmpBO->getOperand(1); - const SCEV *AndLHSSCEV = SE->getSCEV(AndLHS); - const SCEV *AndRHSSCEV = SE->getSCEV(AndRHS); - if (isa(AndLHSSCEV)) { - std::swap(AndLHS, AndRHS); - std::swap(AndLHSSCEV, AndRHSSCEV); - } - - const SCEVConstant *MaskSCEV = dyn_cast(AndRHSSCEV); - if (!MaskSCEV) - return false; - - // The mask must have some trailing ones (otherwise the condition is - // trivial and tells us nothing about the alignment of the left operand). - unsigned TrailingOnes = MaskSCEV->getAPInt().countTrailingOnes(); - if (!TrailingOnes) - return false; - - // Cap the alignment at the maximum with which LLVM can deal (and make sure - // we don't overflow the shift). - uint64_t Alignment; - TrailingOnes = std::min(TrailingOnes, - unsigned(sizeof(unsigned) * CHAR_BIT - 1)); - Alignment = std::min(1u << TrailingOnes, +Value::MaximumAlignment); - - Type *Int64Ty = Type::getInt64Ty(I->getParent()->getParent()->getContext()); - AlignSCEV = SE->getConstant(Int64Ty, Alignment); - - // The LHS might be a ptrtoint instruction, or it might be the pointer - // with an offset. - AAPtr = nullptr; - OffSCEV = nullptr; - if (PtrToIntInst *PToI = dyn_cast(AndLHS)) { - AAPtr = PToI->getPointerOperand(); + assert(AlignOB.Inputs.size() >= 2); + AAPtr = AlignOB.Inputs[0].get(); + // TODO: Consider accumulating the offset to the base. + AAPtr = AAPtr->stripPointerCastsSameRepresentation(); + AlignSCEV = SE->getSCEV(AlignOB.Inputs[1].get()); + AlignSCEV = SE->getTruncateOrZeroExtend(AlignSCEV, Int64Ty); + if (AlignOB.Inputs.size() == 3) + OffSCEV = SE->getSCEV(AlignOB.Inputs[2].get()); + else OffSCEV = SE->getZero(Int64Ty); - } else if (const SCEVAddExpr* AndLHSAddSCEV = - dyn_cast(AndLHSSCEV)) { - // Try to find the ptrtoint; subtract it and the rest is the offset. - for (SCEVAddExpr::op_iterator J = AndLHSAddSCEV->op_begin(), - JE = AndLHSAddSCEV->op_end(); J != JE; ++J) - if (const SCEVUnknown *OpUnk = dyn_cast(*J)) - if (PtrToIntInst *PToI = dyn_cast(OpUnk->getValue())) { - AAPtr = PToI->getPointerOperand(); - OffSCEV = SE->getMinusSCEV(AndLHSAddSCEV, *J); - break; - } - } - - if (!AAPtr) - return false; - - // Sign extend the offset to 64 bits (so that it is like all of the other - // expressions). - unsigned OffSCEVBits = OffSCEV->getType()->getPrimitiveSizeInBits(); - if (OffSCEVBits < 64) - OffSCEV = SE->getSignExtendExpr(OffSCEV, Int64Ty); - else if (OffSCEVBits > 64) - return false; - - AAPtr = AAPtr->stripPointerCasts(); + OffSCEV = SE->getTruncateOrZeroExtend(OffSCEV, Int64Ty); return true; } -bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { +bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall, + unsigned Idx) { Value *AAPtr; const SCEV *AlignSCEV, *OffSCEV; - if (!extractAlignmentInfo(ACall, AAPtr, AlignSCEV, OffSCEV)) + if (!extractAlignmentInfo(ACall, Idx, AAPtr, AlignSCEV, OffSCEV)) return false; // Skip ConstantPointerNull and UndefValue. Assumptions on these shouldn't @@ -317,13 +248,14 @@ bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { continue; if (Instruction *K = dyn_cast(J)) - if (isValidAssumeForContext(ACall, K, DT)) WorkList.push_back(K); } while (!WorkList.empty()) { Instruction *J = WorkList.pop_back_val(); if (LoadInst *LI = dyn_cast(J)) { + if (!isValidAssumeForContext(ACall, J, DT)) + continue; Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV, LI->getPointerOperand(), SE); if (NewAlignment > LI->getAlign()) { @@ -331,6 +263,8 @@ bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { ++NumLoadAlignChanged; } } else if (StoreInst *SI = dyn_cast(J)) { + if (!isValidAssumeForContext(ACall, J, DT)) + continue; Align NewAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV, SI->getPointerOperand(), SE); if (NewAlignment > SI->getAlign()) { @@ -338,6 +272,8 @@ bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { ++NumStoreAlignChanged; } } else if (MemIntrinsic *MI = dyn_cast(J)) { + if (!isValidAssumeForContext(ACall, J, DT)) + continue; Align NewDestAlignment = getNewAlignment(AASCEV, AlignSCEV, OffSCEV, MI->getDest(), SE); @@ -369,7 +305,7 @@ bool AlignmentFromAssumptionsPass::processAssumption(CallInst *ACall) { Visited.insert(J); for (User *UJ : J->users()) { Instruction *K = cast(UJ); - if (!Visited.count(K) && isValidAssumeForContext(ACall, K, DT)) + if (!Visited.count(K)) WorkList.push_back(K); } } @@ -396,8 +332,11 @@ bool AlignmentFromAssumptionsPass::runImpl(Function &F, AssumptionCache &AC, bool Changed = false; for (auto &AssumeVH : AC.assumptions()) - if (AssumeVH) - Changed |= processAssumption(cast(AssumeVH)); + if (AssumeVH) { + CallInst *Call = cast(AssumeVH); + for (unsigned Idx = 0; Idx < Call->getNumOperandBundles(); Idx++) + Changed |= processAssumption(Call, Idx); + } return Changed; } diff --git a/llvm/test/Transforms/AlignmentFromAssumptions/simple.ll b/llvm/test/Transforms/AlignmentFromAssumptions/simple.ll index 14e764f042c7a..610fd448c3b98 100644 --- a/llvm/test/Transforms/AlignmentFromAssumptions/simple.ll +++ b/llvm/test/Transforms/AlignmentFromAssumptions/simple.ll @@ -4,10 +4,7 @@ target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32)] %0 = load i32, i32* %a, align 4 ret i32 %0 @@ -18,11 +15,7 @@ entry: define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %offsetptr = add i64 %ptrint, 24 - %maskedptr = and i64 %offsetptr, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32, i32 24)] %arrayidx = getelementptr inbounds i32, i32* %a, i64 2 %0 = load i32, i32* %arrayidx, align 4 ret i32 %0 @@ -34,11 +27,7 @@ entry: define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %offsetptr = add i64 %ptrint, 28 - %maskedptr = and i64 %offsetptr, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32, i32 28)] %arrayidx = getelementptr inbounds i32, i32* %a, i64 -1 %0 = load i32, i32* %arrayidx, align 4 ret i32 %0 @@ -50,10 +39,7 @@ entry: define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i32 32, i32 0)] %0 = load i32, i32* %a, align 4 ret i32 %0 @@ -64,10 +50,7 @@ entry: define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i32 0)] br label %for.body for.body: ; preds = %entry, %for.body @@ -98,10 +81,7 @@ for.end: ; preds = %for.body ; load(a, i0+i1+i2+32) define void @hoo2(i32* nocapture %a, i64 %id, i64 %num) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i64 0)] %id.mul = shl nsw i64 %id, 6 %num.mul = shl nsw i64 %num, 6 br label %for0.body @@ -147,10 +127,7 @@ return: define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i8 0)] br label %for.body for.body: ; preds = %entry, %for.body @@ -175,16 +152,13 @@ for.end: ; preds = %for.body define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] %arrayidx = getelementptr inbounds i32, i32* %a, i64 %indvars.iv + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i8 32, i8 0)] %0 = load i32, i32* %arrayidx, align 4 %add = add nsw i32 %0, %r.06 %indvars.iv.next = add i64 %indvars.iv, 4 @@ -203,10 +177,7 @@ for.end: ; preds = %for.body define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i128 32, i128 0)] br label %for.body for.body: ; preds = %entry, %for.body @@ -231,10 +202,7 @@ for.end: ; preds = %for.body define i32 @moo(i32* nocapture %a) nounwind uwtable { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + tail call void @llvm.assume(i1 true) ["align"(i32* %a, i16 32)] %0 = bitcast i32* %a to i8* tail call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 64, i1 false) ret i32 undef @@ -246,15 +214,9 @@ entry: define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) - %ptrint1 = ptrtoint i32* %b to i64 - %maskedptr3 = and i64 %ptrint1, 127 - %maskcond4 = icmp eq i64 %maskedptr3, 0 - tail call void @llvm.assume(i1 %maskcond4) + tail call void @llvm.assume(i1 true) ["align"(i32* %b, i32 128)] %0 = bitcast i32* %a to i8* + tail call void @llvm.assume(i1 true) ["align"(i8* %0, i16 32)] %1 = bitcast i32* %b to i8* tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false) ret i32 undef @@ -264,6 +226,19 @@ entry: ; CHECK: ret i32 undef } +define i32 @moo3(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { +entry: + %0 = bitcast i32* %a to i8* + tail call void @llvm.assume(i1 true) ["align"(i8* %0, i16 32), "align"(i32* %b, i32 128)] + %1 = bitcast i32* %b to i8* + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo3 +; CHECK: @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 %0, i8* align 128 %1, i64 64, i1 false) +; CHECK: ret i32 undef +} + declare void @llvm.assume(i1) nounwind declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind diff --git a/llvm/test/Transforms/AlignmentFromAssumptions/simple32.ll b/llvm/test/Transforms/AlignmentFromAssumptions/simple32.ll index 3f0819e3641b3..453899c15c4fb 100644 --- a/llvm/test/Transforms/AlignmentFromAssumptions/simple32.ll +++ b/llvm/test/Transforms/AlignmentFromAssumptions/simple32.ll @@ -7,18 +7,12 @@ define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@foo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 32 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] %0 = load i32, i32* %a, align 4 ret i32 %0 @@ -28,21 +22,13 @@ define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@foo2 ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[OFFSETPTR:%.*]] = add i64 [[PTRINT]], 24 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[OFFSETPTR]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 24) ] ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 2 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 16 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: - %ptrint = ptrtoint i32* %a to i64 - %offsetptr = add i64 %ptrint, 24 - %maskedptr = and i64 %offsetptr, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 24)] %arrayidx = getelementptr inbounds i32, i32* %a, i64 2 %0 = load i32, i32* %arrayidx, align 4 ret i32 %0 @@ -53,21 +39,13 @@ define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@foo2a ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[OFFSETPTR:%.*]] = add i64 [[PTRINT]], 28 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[OFFSETPTR]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32, i64 28) ] ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 -1 ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 32 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: - %ptrint = ptrtoint i32* %a to i64 - %offsetptr = add i64 %ptrint, 28 - %maskedptr = and i64 %offsetptr, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32, i64 28)] %arrayidx = getelementptr inbounds i32, i32* %a, i64 -1 %0 = load i32, i32* %arrayidx, align 4 ret i32 %0 @@ -78,18 +56,12 @@ define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@goo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] ; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 32 ; CHECK-NEXT: ret i32 [[TMP0]] ; entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] %0 = load i32, i32* %a, align 4 ret i32 %0 @@ -99,10 +71,7 @@ define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@hoo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] @@ -119,10 +88,7 @@ define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] ; entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] br label %for.body for.body: ; preds = %entry, %for.body @@ -146,10 +112,7 @@ define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@joo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] @@ -166,10 +129,7 @@ define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] ; entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] br label %for.body for.body: ; preds = %entry, %for.body @@ -193,10 +153,7 @@ define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@koo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] @@ -213,10 +170,7 @@ define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] ; entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] br label %for.body for.body: ; preds = %entry, %for.body @@ -240,10 +194,7 @@ define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-LABEL: define {{[^@]+}}@koo2 ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ -4, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] @@ -260,10 +211,7 @@ define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { ; CHECK-NEXT: ret i32 [[ADD_LCSSA]] ; entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] br label %for.body for.body: ; preds = %entry, %for.body @@ -287,19 +235,13 @@ define i32 @moo(i32* nocapture %a) nounwind uwtable { ; CHECK-LABEL: define {{[^@]+}}@moo ; CHECK-SAME: (i32* nocapture [[A:%.*]]) #1 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i8* ; CHECK-NEXT: tail call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP0]], i8 0, i64 64, i1 false) ; CHECK-NEXT: ret i32 undef ; entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] %0 = bitcast i32* %a to i8* tail call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 64, i1 false) ret i32 undef @@ -310,28 +252,16 @@ define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { ; CHECK-LABEL: define {{[^@]+}}@moo2 ; CHECK-SAME: (i32* nocapture [[A:%.*]], i32* nocapture [[B:%.*]]) #1 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint i32* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 31 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) -; CHECK-NEXT: [[PTRINT1:%.*]] = ptrtoint i32* [[B]] to i64 -; CHECK-NEXT: [[MASKEDPTR3:%.*]] = and i64 [[PTRINT1]], 127 -; CHECK-NEXT: [[MASKCOND4:%.*]] = icmp eq i64 [[MASKEDPTR3]], 0 -; CHECK-NEXT: tail call void @llvm.assume(i1 [[MASKCOND4]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[A]], i64 32) ] +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i32* [[B]], i64 128) ] ; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[A]] to i8* ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[B]] to i8* ; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 32 [[TMP0]], i8* align 128 [[TMP1]], i64 64, i1 false) ; CHECK-NEXT: ret i32 undef ; entry: - %ptrint = ptrtoint i32* %a to i64 - %maskedptr = and i64 %ptrint, 31 - %maskcond = icmp eq i64 %maskedptr, 0 - tail call void @llvm.assume(i1 %maskcond) - %ptrint1 = ptrtoint i32* %b to i64 - %maskedptr3 = and i64 %ptrint1, 127 - %maskcond4 = icmp eq i64 %maskedptr3, 0 - tail call void @llvm.assume(i1 %maskcond4) + call void @llvm.assume(i1 true) ["align"(i32* %a, i64 32)] + call void @llvm.assume(i1 true) ["align"(i32* %b, i64 128)] %0 = bitcast i32* %a to i8* %1 = bitcast i32* %b to i8* tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %0, i8* align 4 %1, i64 64, i1 false) diff --git a/llvm/test/Transforms/Inline/align.ll b/llvm/test/Transforms/Inline/align.ll index ede6c3fa7bcf4..f3a5184564850 100644 --- a/llvm/test/Transforms/Inline/align.ll +++ b/llvm/test/Transforms/Inline/align.ll @@ -23,10 +23,7 @@ define void @foo(float* nocapture %a, float* nocapture readonly %c) #0 { ; CHECK-LABEL: define {{[^@]+}}@foo ; CHECK-SAME: (float* nocapture [[A:%.*]], float* nocapture readonly [[C:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint float* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 127 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[A]], i64 128) ] ; CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4 ; CHECK-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 ; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I]], align 4 @@ -87,14 +84,8 @@ define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture rea ; CHECK-LABEL: define {{[^@]+}}@foo2 ; CHECK-SAME: (float* nocapture [[A:%.*]], float* nocapture [[B:%.*]], float* nocapture readonly [[C:%.*]]) #0 ; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTRINT:%.*]] = ptrtoint float* [[A]] to i64 -; CHECK-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 127 -; CHECK-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) -; CHECK-NEXT: [[PTRINT1:%.*]] = ptrtoint float* [[B]] to i64 -; CHECK-NEXT: [[MASKEDPTR2:%.*]] = and i64 [[PTRINT1]], 127 -; CHECK-NEXT: [[MASKCOND3:%.*]] = icmp eq i64 [[MASKEDPTR2]], 0 -; CHECK-NEXT: call void @llvm.assume(i1 [[MASKCOND3]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[A]], i64 128) ] +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(float* [[B]], i64 128) ] ; CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4 ; CHECK-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5 ; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I]], align 4 diff --git a/llvm/test/Transforms/InstCombine/assume.ll b/llvm/test/Transforms/InstCombine/assume.ll index 6f33e83ee3362..b372f52a2cdf0 100644 --- a/llvm/test/Transforms/InstCombine/assume.ll +++ b/llvm/test/Transforms/InstCombine/assume.ll @@ -377,6 +377,7 @@ define i32 @assumption_conflicts_with_known_bits(i32 %a, i32 %b) { define void @debug_interference(i8 %x) { ; CHECK-LABEL: @debug_interference( ; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[X:%.*]], 0 +; CHECK-NEXT: tail call void @llvm.assume(i1 false) ; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 5, metadata !7, metadata !DIExpression()), !dbg !9 ; CHECK-NEXT: tail call void @llvm.assume(i1 false) ; CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 5, metadata !7, metadata !DIExpression()), !dbg !9 diff --git a/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll b/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll index 61287e35005ff..2605701d231d2 100644 --- a/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll +++ b/llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll @@ -41,10 +41,7 @@ define void @caller1(i1 %c, i64* align 1 %ptr) { ; ASSUMPTIONS-ON-NEXT: br i1 [[C:%.*]], label [[TRUE2_CRITEDGE:%.*]], label [[FALSE1:%.*]] ; ASSUMPTIONS-ON: false1: ; ASSUMPTIONS-ON-NEXT: store volatile i64 1, i64* [[PTR:%.*]], align 8 -; ASSUMPTIONS-ON-NEXT: [[PTRINT:%.*]] = ptrtoint i64* [[PTR]] to i64 -; ASSUMPTIONS-ON-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 7 -; ASSUMPTIONS-ON-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; ASSUMPTIONS-ON-NEXT: tail call void @llvm.assume(i1 [[MASKCOND]]) +; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 true) [ "align"(i64* [[PTR]], i64 8) ] ; ASSUMPTIONS-ON-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 @@ -54,10 +51,7 @@ define void @caller1(i1 %c, i64* align 1 %ptr) { ; ASSUMPTIONS-ON-NEXT: store volatile i64 3, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: ret void ; ASSUMPTIONS-ON: true2.critedge: -; ASSUMPTIONS-ON-NEXT: [[PTRINT_C:%.*]] = ptrtoint i64* [[PTR]] to i64 -; ASSUMPTIONS-ON-NEXT: [[MASKEDPTR_C:%.*]] = and i64 [[PTRINT_C]], 7 -; ASSUMPTIONS-ON-NEXT: [[MASKCOND_C:%.*]] = icmp eq i64 [[MASKEDPTR_C]], 0 -; ASSUMPTIONS-ON-NEXT: tail call void @llvm.assume(i1 [[MASKCOND_C]]) +; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 true) [ "align"(i64* [[PTR]], i64 8) ] ; ASSUMPTIONS-ON-NEXT: store volatile i64 0, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 ; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, i64* [[PTR]], align 8 @@ -94,26 +88,17 @@ false2: ; This test checks that alignment assumptions do not prevent SROA. ; See PR45763. -define internal void @callee2(i64* noalias sret align 8 %arg) { +define internal void @callee2(i64* noalias sret align 32 %arg) { store i64 0, i64* %arg, align 8 ret void } define amdgpu_kernel void @caller2() { -; ASSUMPTIONS-OFF-LABEL: @caller2( -; ASSUMPTIONS-OFF-NEXT: ret void -; -; ASSUMPTIONS-ON-LABEL: @caller2( -; ASSUMPTIONS-ON-NEXT: [[ALLOCA:%.*]] = alloca i64, align 8, addrspace(5) -; ASSUMPTIONS-ON-NEXT: [[CAST:%.*]] = addrspacecast i64 addrspace(5)* [[ALLOCA]] to i64* -; ASSUMPTIONS-ON-NEXT: [[PTRINT:%.*]] = ptrtoint i64* [[CAST]] to i64 -; ASSUMPTIONS-ON-NEXT: [[MASKEDPTR:%.*]] = and i64 [[PTRINT]], 7 -; ASSUMPTIONS-ON-NEXT: [[MASKCOND:%.*]] = icmp eq i64 [[MASKEDPTR]], 0 -; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 [[MASKCOND]]) -; ASSUMPTIONS-ON-NEXT: ret void +; CHECK-LABEL: @caller2( +; CHECK-NEXT: ret void ; %alloca = alloca i64, align 8, addrspace(5) %cast = addrspacecast i64 addrspace(5)* %alloca to i64* - call void @callee2(i64* sret align 8 %cast) + call void @callee2(i64* sret align 32 %cast) ret void } diff --git a/llvm/test/Verifier/assume-bundles.ll b/llvm/test/Verifier/assume-bundles.ll index 302421715c797..6e260f25129ee 100644 --- a/llvm/test/Verifier/assume-bundles.ll +++ b/llvm/test/Verifier/assume-bundles.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: not opt -verify < %s 2>&1 | FileCheck %s declare void @llvm.assume(i1) @@ -6,14 +7,21 @@ define void @func(i32* %P, i32 %P1, i32* %P2, i32* %P3) { ; CHECK: tags must be valid attribute names call void @llvm.assume(i1 true) ["adazdazd"()] ; CHECK: the second argument should be a constant integral value - call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1)] + call void @llvm.assume(i1 true) ["dereferenceable"(i32* %P, i32 %P1)] ; CHECK: to many arguments - call void @llvm.assume(i1 true) ["align"(i32* %P, i32 8, i32 8)] + call void @llvm.assume(i1 true) ["dereferenceable"(i32* %P, i32 8, i32 8)] ; CHECK: this attribute should have 2 arguments - call void @llvm.assume(i1 true) ["align"(i32* %P)] + call void @llvm.assume(i1 true) ["dereferenceable"(i32* %P)] ; CHECK: this attribute has no argument - call void @llvm.assume(i1 true) ["align"(i32* %P, i32 4), "cold"(i32* %P)] + call void @llvm.assume(i1 true) ["dereferenceable"(i32* %P, i32 4), "cold"(i32* %P)] ; CHECK: this attribute should have one argument call void @llvm.assume(i1 true) ["noalias"()] + call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1, i32 4)] +; CHECK: alignment assumptions should have 2 or 3 arguments + call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1, i32 4, i32 4)] +; CHECK: second argument should be an integer + call void @llvm.assume(i1 true) ["align"(i32* %P, i32* %P2)] +; CHECK: third argument should be an integer if present + call void @llvm.assume(i1 true) ["align"(i32* %P, i32 %P1, i32* %P2)] ret void } diff --git a/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp b/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp index d35a77fa379be..946368e1cb947 100644 --- a/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp +++ b/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp @@ -546,3 +546,41 @@ TEST(AssumeQueryAPI, AssumptionCache) { ASSERT_EQ(AR[0].Index, 1u); ASSERT_EQ(AR[0].Assume, &*First); } + +TEST(AssumeQueryAPI, Alignment) { + LLVMContext C; + SMDiagnostic Err; + std::unique_ptr Mod = parseAssemblyString( + "declare void @llvm.assume(i1)\n" + "define void @test(i32* %P, i32* %P1, i32* %P2, i32 %I3, i1 %B) {\n" + "call void @llvm.assume(i1 true) [\"align\"(i32* %P, i32 8, i32 %I3)]\n" + "call void @llvm.assume(i1 true) [\"align\"(i32* %P1, i32 %I3, i32 " + "%I3)]\n" + "call void @llvm.assume(i1 true) [\"align\"(i32* %P2, i32 16, i32 8)]\n" + "ret void\n}\n", + Err, C); + if (!Mod) + Err.print("AssumeQueryAPI", errs()); + + Function *F = Mod->getFunction("test"); + BasicBlock::iterator Start = F->begin()->begin(); + IntrinsicInst *II; + RetainedKnowledge RK; + II = cast(&*Start); + RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]); + ASSERT_EQ(RK.AttrKind, Attribute::Alignment); + ASSERT_EQ(RK.WasOn, F->getArg(0)); + ASSERT_EQ(RK.ArgValue, 1u); + Start++; + II = cast(&*Start); + RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]); + ASSERT_EQ(RK.AttrKind, Attribute::Alignment); + ASSERT_EQ(RK.WasOn, F->getArg(1)); + ASSERT_EQ(RK.ArgValue, 1u); + Start++; + II = cast(&*Start); + RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]); + ASSERT_EQ(RK.AttrKind, Attribute::Alignment); + ASSERT_EQ(RK.WasOn, F->getArg(2)); + ASSERT_EQ(RK.ArgValue, 8u); +} From c9b625d09aeccd70bc564dfd4f00002d0156bcc2 Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Mon, 13 Jul 2020 23:17:58 +0000 Subject: [PATCH 171/771] [Sanitizers] Ensure clock_getcpuclockid interceptor <= 80 chars --- .../lib/sanitizer_common/sanitizer_common_interceptors.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index 4b02ad2670fef..d7e0bba762941 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -2200,7 +2200,8 @@ INTERCEPTOR(int, clock_settime, u32 clk_id, const void *tp) { #endif #if SANITIZER_INTERCEPT_CLOCK_GETCPUCLOCKID -INTERCEPTOR(int, clock_getcpuclockid, pid_t pid, __sanitizer_clockid_t *clockid) { +INTERCEPTOR(int, clock_getcpuclockid, pid_t pid, + __sanitizer_clockid_t *clockid) { void *ctx; COMMON_INTERCEPTOR_ENTER(ctx, clock_getcpuclockid, pid, clockid); int res = REAL(clock_getcpuclockid)(pid, clockid); From 66550c36f43b32a5be6acdc88a346ca8ac5af368 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Mon, 13 Jul 2020 16:10:45 -0700 Subject: [PATCH 172/771] [ORC] Fix typo in parameter name. --- llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h b/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h index 9f2cdf0292a73..5061c15cf4c96 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/OrcABISupport.h @@ -70,7 +70,7 @@ class OrcGenericABI { } static void writeTrampolines(char *TrampolineBlockWorkingMem, - JITTargetAddress TrampolineBlockTragetAddr, + JITTargetAddress TrampolineBlockTargetAddr, JITTargetAddress ResolverAddr, unsigned NumTrampolines) { llvm_unreachable("writeTrampolines is not supported by the generic host " From caf395ee8c28028d5af0f1455cd5ef134432124c Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Mon, 13 Jul 2020 14:12:32 -0700 Subject: [PATCH 173/771] Reapply "[llvm] Native size estimator for training -Oz inliner" This reverts commit 9908a3b9f521c954cbf6adcec35b14b2f6c8da49. The fix was to exclude the content of TFUtils.h (automatically included in the LLVM_Analysis module, when LLVM_ENABLE_MODULES is enabled). Differential Revision: https://reviews.llvm.org/D82817 --- llvm/CMakeLists.txt | 12 + .../Analysis/InlineSizeEstimatorAnalysis.h | 35 + llvm/include/llvm/Analysis/Utils/TFUtils.h | 138 + llvm/lib/Analysis/CMakeLists.txt | 40 +- .../Analysis/InlineSizeEstimatorAnalysis.cpp | 299 + llvm/lib/Analysis/TFUtils.cpp | 143 + llvm/lib/Passes/PassBuilder.cpp | 1 + llvm/lib/Passes/PassRegistry.def | 1 + llvm/unittests/Analysis/CMakeLists.txt | 12 +- .../InlineSizeEstimatorAnalysisTest.cpp | 101 + .../ir2native_x86_64_model/saved_model.pbtxt | 10596 ++++++++++++++++ .../variables/variables.data-00000-of-00001 | Bin 0 -> 88424 bytes .../variables/variables.index | Bin 0 -> 398 bytes llvm/unittests/Analysis/TFUtilsTest.cpp | 98 + 14 files changed, 11466 insertions(+), 10 deletions(-) create mode 100644 llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h create mode 100644 llvm/include/llvm/Analysis/Utils/TFUtils.h create mode 100644 llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp create mode 100644 llvm/lib/Analysis/TFUtils.cpp create mode 100644 llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp create mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt create mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001 create mode 100644 llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index create mode 100644 llvm/unittests/Analysis/TFUtilsTest.cpp diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index de2887b64c2a9..4e14e61fcacd6 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -981,6 +981,18 @@ if (NOT TENSORFLOW_AOT_PATH STREQUAL "") ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/tf_runtime) endif() +set(TENSORFLOW_C_LIB_PATH "" CACHE PATH "Path to TensorFlow C library install") +find_library(tensorflow_c_api tensorflow PATHS ${TENSORFLOW_C_LIB_PATH}/lib) + +# Similar to the above Tensorflow dependency, please refer to the same script. +# In this case, the latest C API library is available for download from +# https://www.tensorflow.org/install/lang_c +if (tensorflow_c_api) + set(LLVM_HAVE_TF_API "ON" CACHE BOOL "Full Tensorflow API available") + add_definitions("-DLLVM_HAVE_TF_API") + include_directories(${TENSORFLOW_C_LIB_PATH}/include) +endif() + # Put this before tblgen. Else we have a circular dependence. add_subdirectory(lib/Demangle) add_subdirectory(lib/Support) diff --git a/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h b/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h new file mode 100644 index 0000000000000..29a6f59146748 --- /dev/null +++ b/llvm/include/llvm/Analysis/InlineSizeEstimatorAnalysis.h @@ -0,0 +1,35 @@ +//===- InlineSizeEstimatorAnalysis.h - ML size estimator --------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// + +#ifndef LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H +#define LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { +class Function; + +class TFModelEvaluator; +class InlineSizeEstimatorAnalysis + : public AnalysisInfoMixin { +public: + InlineSizeEstimatorAnalysis(); + InlineSizeEstimatorAnalysis(InlineSizeEstimatorAnalysis &&); + ~InlineSizeEstimatorAnalysis(); + + static AnalysisKey Key; + using Result = Optional; + Result run(const Function &F, FunctionAnalysisManager &FAM); + static bool isEvaluatorRequested(); + +private: + std::unique_ptr Evaluator; +}; +} // namespace llvm +#endif // LLVM_ANALYSIS_INLINESIZEESTIMATORANALYSIS_H \ No newline at end of file diff --git a/llvm/include/llvm/Analysis/Utils/TFUtils.h b/llvm/include/llvm/Analysis/Utils/TFUtils.h new file mode 100644 index 0000000000000..b7de199753a6f --- /dev/null +++ b/llvm/include/llvm/Analysis/Utils/TFUtils.h @@ -0,0 +1,138 @@ +//===- TFUtils.h - utilities for tensorflow C API ---------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +#ifndef LLVM_ANALYSIS_UTILS_TFUTILS_H +#define LLVM_ANALYSIS_UTILS_TFUTILS_H + +#ifdef LLVM_HAVE_TF_API +#include "tensorflow/c/c_api.h" +#include "llvm/IR/LLVMContext.h" + +#include +#include + +namespace llvm { + +/// Load a SavedModel, find the given inputs and outputs, and setup storage +/// for input tensors. The user is responsible for correctly dimensioning the +/// input tensors and setting their values before calling evaluate(). +/// To initialize: +/// - construct the object +/// - initialize the input tensors using initInput. Indices must correspond to +/// indices in the InputNames used at construction. +/// To use: +/// - set input values by using getInput to get each input tensor, and then +/// setting internal scalars, for all dimensions (tensors are row-major: +/// https://github.com/tensorflow/tensorflow/blob/r1.5/tensorflow/c/c_api.h#L205) +/// - prepare an output vector of TF_Output* type, with the correct number of +/// outputs (i.e. same as OutputNames). Initialize the vector with nullptr +/// values. +/// - call evaluate. The input tensors' values are not consumed after this, and +/// may still be read. +/// - use the outputs in the output vector +/// - deallocate each output tensor in the output vector, using TF_DeleteTensor. +class TFModelEvaluator final { +public: + /// The result of a model evaluation. Handles the lifetime of the output + /// TF_Tensor objects, which means that their values need to be used before + /// the EvaluationResult's dtor is called. + class EvaluationResult { + public: + ~EvaluationResult() { + for (auto *P : Output) + if (P) + TF_DeleteTensor(P); + } + + EvaluationResult(const EvaluationResult &) = delete; + EvaluationResult(EvaluationResult &&Other) + : OutputSize(Other.OutputSize), Output(std::move(Other.Output)) { + Other.Output.clear(); + }; + + /// Get a pointer to the first element of the tensor at Index. + template T *getTensorValue(size_t Index) { + return static_cast(TF_TensorData(Output[Index])); + } + + private: + friend class TFModelEvaluator; + EvaluationResult(size_t OutputSize) + : OutputSize(OutputSize), Output(OutputSize){}; + + const size_t OutputSize; + std::vector Output; + }; + + using TFGraphPtr = std::unique_ptr; + using TFSessionOptionsPtr = + std::unique_ptr; + using TFStatusPtr = std::unique_ptr; + + TFModelEvaluator(StringRef SavedModelPath, + const std::vector &InputNames, + const std::vector &OutputNames, + const char *Tags = "serve"); + ~TFModelEvaluator(); + TFModelEvaluator(const TFModelEvaluator &) = delete; + TFModelEvaluator(TFModelEvaluator &&) = delete; + + /// Evaluate the model, assuming it is valid. Returns None if the evaluation + /// fails or the model is invalid, or an EvaluationResult otherwise. The + /// inputs are assumed to have been already provided via getInput(). When + /// returning None, it also marks the object invalid. Pass an Output vector + /// with the same size as OutputNames, but with nullptr values. evaluate() + /// will populate it with tensors, matching in index the corresponding + /// OutputNames. The caller is responsible for the deallocation of those + /// tensors, using TF_DeleteTensor. + Optional evaluate(); + + /// Provides access to the input vector. It is already dimensioned correctly, + /// but the values need to be allocated by the user. + std::vector &getInput() { return Input; } + + /// Returns true if the tensorflow model was loaded successfully, false + /// otherwise. + bool isValid() const { return !!Session; } + + /// Initialize the input at Index as a tensor of the given type and dimensions + void initInput(int Index, TF_DataType Type, + const std::vector &Dimensions); + +private: + /// The objects necessary for carrying out an evaluation of the SavedModel. + /// They are expensive to set up, and we maintain them accross all the + /// evaluations of the model. + TF_Session *Session = nullptr; + TFGraphPtr Graph; + TFSessionOptionsPtr Options; + + /// The specification of the input nodes. + std::vector InputFeed; + + /// The input tensors. They must match by index of the corresponding InputFeed + /// value. We set up the tensors once and just mutate theirs scalars before + /// each evaluation. The input tensors keep their value after an evaluation. + std::vector Input; + + /// The specification of the output nodes. When evaluating, the tensors in the + /// output tensor vector must match by index the corresponding element in the + /// OutputFeed. + std::vector OutputFeed; + + /// Reusable utility for deleting the session. + void deleteSession(); + + /// Reusable utility for ensuring we can bind the requested Name to a node in + /// the SavedModel Graph. + bool checkReportAndReset(const TF_Output &Output, StringRef Name); +}; +} // namespace llvm + +#endif // LLVM_HAVE_TF_API +#endif // LLVM_ANALYSIS_UTILS_TFUTILS_H diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index a317579ecc836..703623396d96a 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -1,17 +1,35 @@ set(CommonMLSources MLInlineAdvisor.cpp) set(ReleaseModeMLSources ReleaseModeModelRunner.cpp) +set(DevelopmentModeMLSources TFUtils.cpp) -if (DEFINED LLVM_HAVE_TF_AOT) - include(TensorFlowCompile) - tfcompile(models/inliner serve action InlinerSizeModel llvm::InlinerSizeModel) - list(APPEND ReleaseModeMLSources - $ - ${GENERATED_OBJS} - ) - set(MLPolicySources ${CommonMLSources} ${ReleaseModeMLSources}) +if (DEFINED LLVM_HAVE_TF_AOT OR DEFINED LLVM_HAVE_TF_API) + set(MLPolicySources ${CommonMLSources}) + if (DEFINED LLVM_HAVE_TF_AOT) + include(TensorFlowCompile) + tfcompile(models/inliner serve action InlinerSizeModel llvm::InlinerSizeModel) + list(APPEND ReleaseModeMLSources + $ + ${GENERATED_OBJS} + ) + LIST(APPEND MLPolicySources ${ReleaseModeMLSources}) + else() + LIST(APPEND LLVM_OPTIONAL_SOURCES ${ReleaseModeMLSources}) + endif() + + if (DEFINED LLVM_HAVE_TF_API) + LIST(APPEND MLPolicySources ${DevelopmentModeMLSources}) + LIST(APPEND MLLinkDeps ${tensorflow_c_api}) + else() + LIST(APPEND LLVM_OPTIONAL_SOURCES ${DevelopmentModeMLSources}) + endif() else() - set(LLVM_OPTIONAL_SOURCES ${CommonMLSources} ${ReleaseModeMLSources}) + LIST(APPEND LLVM_OPTIONAL_SOURCES + ${CommonMLSources} + ${DevelopmentModeMLSources} + ${ReleaseModeMLSources} + ) endif() + add_llvm_component_library(LLVMAnalysis AliasAnalysis.cpp @@ -57,6 +75,7 @@ add_llvm_component_library(LLVMAnalysis InlineCost.cpp InlineAdvisor.cpp InlineFeaturesAnalysis.cpp + InlineSizeEstimatorAnalysis.cpp InstCount.cpp InstructionPrecedenceTracking.cpp InstructionSimplify.cpp @@ -124,4 +143,7 @@ add_llvm_component_library(LLVMAnalysis DEPENDS intrinsics_gen + + LINK_LIBS + ${MLLinkDeps} ) diff --git a/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp b/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp new file mode 100644 index 0000000000000..1d1952ae6cbbe --- /dev/null +++ b/llvm/lib/Analysis/InlineSizeEstimatorAnalysis.cpp @@ -0,0 +1,299 @@ +//===- InlineSizeEstimatorAnalysis.cpp - IR to native size from ML model --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This implements feature and label extraction for offline supervised learning +// of a IR to native size model. +// +//===----------------------------------------------------------------------===// +#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h" + +#ifdef LLVM_HAVE_TF_API +#include "llvm/Analysis/Utils/TFUtils.h" +#endif +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/PassManager.h" +#include "llvm/MC/MCAsmLayout.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include + +using namespace llvm; + +AnalysisKey InlineSizeEstimatorAnalysis::Key; + +#define DEBUG_TYPE "inline-size-estimator" + +#ifdef LLVM_HAVE_TF_API +cl::opt TFIR2NativeModelPath( + "ml-inliner-ir2native-model", cl::Hidden, + cl::desc("Path to saved model evaluating native size from IR.")); + +namespace { +unsigned getMaxInstructionID() { +#define LAST_OTHER_INST(NR) return NR; +#include "llvm/IR/Instruction.def" +} + +class IRToNativeSizeLearning { +public: + enum class NamedFeatureIndex : size_t { + InitialSize, + Blocks, + Calls, + IsLocal, + IsLinkOnceODR, + IsLinkOnce, + Loops, + MaxLoopDepth, + MaxDomTreeLevel, + + NumNamedFeatures + }; + static const size_t NumNamedFeatures = + static_cast(NamedFeatureIndex::NumNamedFeatures); + struct FunctionFeatures { + static std::vector> + ImportantInstructionSuccessions; + static const size_t FeatureCount; + + std::array NamedFeatures = {0}; + std::vector InstructionHistogram; + std::vector InstructionPairHistogram; + + void fillTensor(int32_t *Ptr) const; + int32_t &operator[](NamedFeatureIndex Pos) { + return NamedFeatures[static_cast(Pos)]; + } + }; + IRToNativeSizeLearning() = default; + + static FunctionFeatures getFunctionFeatures(Function &F, + FunctionAnalysisManager &FAM); + +private: + /// Sort once the feature tuples. + struct SortFeatureTuples { + bool IsSorted = false; + SortFeatureTuples() { + std::sort(FunctionFeatures::ImportantInstructionSuccessions.begin(), + FunctionFeatures::ImportantInstructionSuccessions.end()); + IsSorted = true; + } + }; + + static llvm::ManagedStatic TupleSorter; + + static bool ensureSortedTuples() { return TupleSorter->IsSorted; } +}; +llvm::ManagedStatic + IRToNativeSizeLearning::TupleSorter; + +// This is a point in time - we determined including these pairs of +// consecutive instructions (in the IR layout available at inline time) as +// features improves the model performance. We want to move away from manual +// feature selection. +// The vector is given in opcode pairs rather than labels because 1) labels +// weren't readily available, and 2) the successions were hand - extracted +std::vector> + IRToNativeSizeLearning::FunctionFeatures::ImportantInstructionSuccessions = + {{1, 34}, {15, 27}, {53, 53}, {53, 34}, {1, 11}, {32, 2}, {2, 48}, + {28, 48}, {1, 45}, {49, 32}, {57, 56}, {55, 53}, {1, 28}, {57, 34}, + {1, 1}, {32, 28}, {32, 15}, {49, 28}, {53, 1}, {2, 53}, {48, 34}, + {28, 53}, {2, 32}, {1, 40}, {32, 48}, {29, 56}, {56, 32}, {55, 56}, + {48, 56}, {1, 31}, {33, 34}, {2, 28}, {1, 12}, {55, 1}, {31, 31}, + {65, 1}, {33, 56}, {32, 32}, {13, 13}, {1, 26}, {13, 26}, {2, 1}, + {1, 33}, {47, 49}, {64, 1}, {2, 38}, {34, 53}, {48, 2}, {55, 34}, + {34, 32}, {1, 5}, {56, 13}, {2, 2}, {2, 49}, {33, 2}, {49, 39}, + {56, 49}, {33, 49}, {32, 39}, {39, 57}, {29, 33}, {31, 34}, {32, 29}, + {47, 15}, {13, 34}, {2, 33}, {32, 49}, {49, 34}, {56, 33}, {1, 30}, + {33, 33}, {31, 33}, {2, 29}, {56, 7}, {32, 13}, {2, 55}, {56, 56}, + {2, 34}, {1, 42}, {34, 49}, {1, 20}, {32, 33}, {1, 25}, {53, 28}, + {1, 14}, {31, 49}, {28, 2}, {2, 13}, {2, 56}, {1, 32}, {56, 53}, + {65, 65}, {33, 53}, {64, 64}, {13, 2}, {34, 33}, {1, 4}, {49, 2}, + {1, 9}, {56, 1}, {33, 1}, {53, 57}, {32, 53}, {13, 56}, {32, 56}, + {55, 55}, {1, 18}, {49, 56}, {34, 34}, {1, 7}, {56, 64}, {32, 1}, + {13, 33}, {55, 28}, {49, 33}, {57, 57}, {56, 34}, {34, 56}, {33, 32}, + {32, 40}, {1, 29}, {53, 2}, {34, 1}, {32, 34}, {49, 49}, {1, 24}, + {40, 34}, {1, 13}, {38, 34}, {29, 2}, {34, 2}, {1, 39}, {1, 22}, + {1, 27}, {49, 1}, {1, 8}, {56, 2}}; + +// We have: 9 calculated features (the features here); 1 feature for each +// instruction opcode; and 1 feature for each manually-identified sequence. +// For the latter 2, we build a histogram: we count the number of +// occurrences of each instruction opcode or succession of instructions, +// respectively. +// Note that instruction opcodes start from 1. For convenience, we also have an +// always 0 feature for the '0' opcode, hence the extra 1. +const size_t IRToNativeSizeLearning::FunctionFeatures::FeatureCount = + IRToNativeSizeLearning::FunctionFeatures::ImportantInstructionSuccessions + .size() + + getMaxInstructionID() + 1 + IRToNativeSizeLearning::NumNamedFeatures; + +size_t getSize(Function &F, TargetTransformInfo &TTI) { + size_t Ret = 0; + for (auto &BB : F) + for (auto &I : BB) + Ret += TTI.getInstructionCost( + &I, TargetTransformInfo::TargetCostKind::TCK_CodeSize); + return Ret; +} + +size_t getSize(Function &F, FunctionAnalysisManager &FAM) { + auto &TTI = FAM.getResult(F); + return getSize(F, TTI); +} + +unsigned getMaxDominatorTreeDepth(const Function &F, + const DominatorTree &Tree) { + unsigned Ret = 0; + for (auto &BB : F) + if (auto *TN = Tree.getNode(&BB)) + Ret = std::max(Ret, TN->getLevel()); + return Ret; +} +} // namespace + +IRToNativeSizeLearning::FunctionFeatures +IRToNativeSizeLearning::getFunctionFeatures(Function &F, + FunctionAnalysisManager &FAM) { + assert(ensureSortedTuples() && "expected lazy initialization"); + + auto &DomTree = FAM.getResult(F); + FunctionFeatures FF; + size_t InstrCount = getMaxInstructionID() + 1; + FF.InstructionHistogram.resize(InstrCount); + + FF.InstructionPairHistogram.resize( + FunctionFeatures::ImportantInstructionSuccessions.size()); + + auto StartID = 0; + auto LastID = StartID; + auto getPairIndex = [](size_t a, size_t b) { + auto I = + std::find(FunctionFeatures::ImportantInstructionSuccessions.begin(), + FunctionFeatures::ImportantInstructionSuccessions.end(), + std::make_pair(a, b)); + if (I == FunctionFeatures::ImportantInstructionSuccessions.end()) + return -1; + return static_cast(std::distance( + FunctionFeatures::ImportantInstructionSuccessions.begin(), I)); + }; + + // We don't want debug calls, because they'd just add noise. + for (auto &BB : F) { + for (auto I = BB.instructionsWithoutDebug().begin(), + E = BB.instructionsWithoutDebug().end(); + I != E; ++I) { + auto ID = I->getOpcode(); + + ++FF.InstructionHistogram[ID]; + int PairIndex = getPairIndex(LastID, ID); + if (PairIndex >= 0) + ++FF.InstructionPairHistogram[PairIndex]; + LastID = ID; + if (isa(*I)) + ++FF[NamedFeatureIndex::Calls]; + } + } + + FF[NamedFeatureIndex::InitialSize] = getSize(F, FAM); + FF[NamedFeatureIndex::IsLocal] = F.hasLocalLinkage(); + FF[NamedFeatureIndex::IsLinkOnceODR] = F.hasLinkOnceODRLinkage(); + FF[NamedFeatureIndex::IsLinkOnce] = F.hasLinkOnceLinkage(); + FF[NamedFeatureIndex::Blocks] = + std::distance(F.getBasicBlockList().begin(), F.getBasicBlockList().end()); + auto &LI = FAM.getResult(F); + FF[NamedFeatureIndex::Loops] = std::distance(LI.begin(), LI.end()); + for (auto &L : LI) + FF[NamedFeatureIndex::MaxLoopDepth] = + std::max(FF[NamedFeatureIndex::MaxLoopDepth], + static_cast(L->getLoopDepth())); + FF[NamedFeatureIndex::MaxDomTreeLevel] = getMaxDominatorTreeDepth(F, DomTree); + return FF; +} + +void IRToNativeSizeLearning::FunctionFeatures::fillTensor(int32_t *Ptr) const { + std::copy(NamedFeatures.begin(), NamedFeatures.end(), Ptr); + Ptr += NamedFeatures.size(); + std::copy(InstructionHistogram.begin(), InstructionHistogram.end(), Ptr); + Ptr += InstructionHistogram.size(); + std::copy(InstructionPairHistogram.begin(), InstructionPairHistogram.end(), + Ptr); +} + +bool InlineSizeEstimatorAnalysis::isEvaluatorRequested() { + return !TFIR2NativeModelPath.empty(); +} + +InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis() { + if (!isEvaluatorRequested()) { + return; + } + std::vector InputNames{"serving_default_input_1"}; + std::vector OutputName{"StatefulPartitionedCall"}; + Evaluator = std::make_unique( + TFIR2NativeModelPath.getValue().c_str(), InputNames, OutputName); + if (!Evaluator || !Evaluator->isValid()) { + Evaluator.reset(); + return; + } + static const std::vector Dim{ + 1, static_cast( + IRToNativeSizeLearning::FunctionFeatures::FeatureCount)}; + + Evaluator->initInput(0, TF_INT32, Dim); +} + +InlineSizeEstimatorAnalysis::Result +InlineSizeEstimatorAnalysis::run(const Function &F, + FunctionAnalysisManager &FAM) { + if (!Evaluator) + return None; + auto Features = IRToNativeSizeLearning::getFunctionFeatures( + const_cast(F), FAM); + int32_t *V = static_cast(TF_TensorData(Evaluator->getInput()[0])); + Features.fillTensor(V); + auto ER = Evaluator->evaluate(); + if (!ER) + return None; + float Ret = *ER->getTensorValue(0); + if (Ret < 0.0) + Ret = 0.0; + return static_cast(Ret); +} + +InlineSizeEstimatorAnalysis::~InlineSizeEstimatorAnalysis() {} +InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis( + InlineSizeEstimatorAnalysis &&Other) + : Evaluator(std::move(Other.Evaluator)) {} + +#else +namespace llvm { +class TFModelEvaluator {}; +} // namespace llvm +InlineSizeEstimatorAnalysis::InlineSizeEstimatorAnalysis() {} +InlineSizeEstimatorAnalysis ::InlineSizeEstimatorAnalysis( + InlineSizeEstimatorAnalysis &&) {} +InlineSizeEstimatorAnalysis::~InlineSizeEstimatorAnalysis() {} +InlineSizeEstimatorAnalysis::Result +InlineSizeEstimatorAnalysis::run(const Function &F, + FunctionAnalysisManager &FAM) { + return None; +} +bool InlineSizeEstimatorAnalysis::isEvaluatorRequested() { return false; } +#endif \ No newline at end of file diff --git a/llvm/lib/Analysis/TFUtils.cpp b/llvm/lib/Analysis/TFUtils.cpp new file mode 100644 index 0000000000000..6cd5b5c9b4eae --- /dev/null +++ b/llvm/lib/Analysis/TFUtils.cpp @@ -0,0 +1,143 @@ +//===- TFUtils.cpp - tensorflow evaluation utilities ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements utilities for interfacing with tensorflow C APIs. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/Utils/TFUtils.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/raw_ostream.h" + +#include "tensorflow/c/c_api_experimental.h" + +#include + +using namespace llvm; + +namespace { + +struct TFInitializer { + TFInitializer() { + assert(!IsInitialized && "TFInitialized should be called only once"); + int Argc = 1; + const char *Name = ""; + const char **NamePtr = &Name; + TF_InitMain(Name, &Argc, const_cast(&NamePtr)); + IsInitialized = true; + } + bool IsInitialized = false; +}; + +llvm::ManagedStatic TFLibInitializer; + +bool ensureInitTF() { return TFLibInitializer->IsInitialized; } + +TFModelEvaluator::TFGraphPtr createTFGraph() { + return TFModelEvaluator::TFGraphPtr(TF_NewGraph(), &TF_DeleteGraph); +} + +TFModelEvaluator::TFStatusPtr createTFStatus() { + return TFModelEvaluator::TFStatusPtr(TF_NewStatus(), &TF_DeleteStatus); +} + +TFModelEvaluator::TFSessionOptionsPtr createTFSessionOptions() { + return TFModelEvaluator::TFSessionOptionsPtr(TF_NewSessionOptions(), + &TF_DeleteSessionOptions); +} +} // namespace + +TFModelEvaluator::TFModelEvaluator(StringRef SavedModelPath, + const std::vector &InputNames, + const std::vector &OutputNames, + const char *Tags) + : Graph(createTFGraph()), Options(createTFSessionOptions()), + InputFeed(InputNames.size()), Input(InputNames.size()), + OutputFeed(OutputNames.size()) { + if (!ensureInitTF()) { + errs() << "Tensorflow should have been initialized"; + return; + } + auto Status = createTFStatus(); + + Session = TF_LoadSessionFromSavedModel(Options.get(), nullptr, + SavedModelPath.str().c_str(), &Tags, 1, + Graph.get(), nullptr, Status.get()); + if (TF_GetCode(Status.get()) != TF_Code::TF_OK) { + errs() << TF_Message(Status.get()); + deleteSession(); + } + for (size_t I = 0; I < InputNames.size(); ++I) { + InputFeed[I] = { + TF_GraphOperationByName(Graph.get(), (InputNames[I]).c_str()), 0}; + if (!checkReportAndReset(InputFeed[I], InputNames[I])) + return; + } + for (size_t I = 0; I < OutputNames.size(); ++I) { + OutputFeed[I] = { + TF_GraphOperationByName(Graph.get(), (OutputNames[I]).c_str()), 0}; + if (!checkReportAndReset(OutputFeed[I], OutputNames[I])) + return; + } +} + +TFModelEvaluator::~TFModelEvaluator() { + for (auto *T : Input) { + TF_DeleteTensor(T); + } + deleteSession(); +} + +bool TFModelEvaluator::checkReportAndReset(const TF_Output &Output, + StringRef Name) { + if (Output.oper) + return true; + errs() << "Could not find TF_Output named: " + Name; + deleteSession(); + return false; +} + +void TFModelEvaluator::deleteSession() { + if (Session == nullptr) + return; + auto Status = createTFStatus(); + TF_DeleteSession(Session, Status.get()); + Session = nullptr; + if (TF_GetCode(Status.get()) != TF_Code::TF_OK) + errs() << "Could not delete TF session"; +} + +Optional TFModelEvaluator::evaluate() { + if (!isValid()) + return None; + EvaluationResult Ret(OutputFeed.size()); + auto Status = createTFStatus(); + TF_SessionRun(Session, nullptr, InputFeed.data(), Input.data(), Input.size(), + OutputFeed.data(), Ret.Output.data(), Ret.Output.size(), + nullptr, 0, nullptr, Status.get()); + if (TF_GetCode(Status.get()) != TF_Code::TF_OK) { + errs() << TF_Message(Status.get()); + deleteSession(); + return None; + } + return Ret; +} + +void TFModelEvaluator::initInput(int Index, TF_DataType Type, + const std::vector &Dimensions) { + int64_t TotalSize = TF_DataTypeSize(Type); + for (auto &D : Dimensions) + TotalSize *= D; + + Input[Index] = + TF_AllocateTensor(Type, Dimensions.data(), Dimensions.size(), TotalSize); + std::memset(TF_TensorData(Input[Index]), 0, TotalSize); +} \ No newline at end of file diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 53158e7aabab0..537d300fee557 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -35,6 +35,7 @@ #include "llvm/Analysis/IVUsers.h" #include "llvm/Analysis/InlineAdvisor.h" #include "llvm/Analysis/InlineFeaturesAnalysis.h" +#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h" #include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Analysis/LazyValueInfo.h" #include "llvm/Analysis/LoopAccessAnalysis.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index eb2b740db5612..dfdfc3d05976a 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -133,6 +133,7 @@ FUNCTION_ANALYSIS("loops", LoopAnalysis()) FUNCTION_ANALYSIS("lazy-value-info", LazyValueAnalysis()) FUNCTION_ANALYSIS("da", DependenceAnalysis()) FUNCTION_ANALYSIS("inliner-features", InlineFeaturesAnalysis()) +FUNCTION_ANALYSIS("inliner-size-estimator", InlineSizeEstimatorAnalysis()) FUNCTION_ANALYSIS("memdep", MemoryDependenceAnalysis()) FUNCTION_ANALYSIS("memoryssa", MemorySSAAnalysis()) FUNCTION_ANALYSIS("phi-values", PhiValuesAnalysis()) diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt index 42f7dd3c06101..59ad444d32fb4 100644 --- a/llvm/unittests/Analysis/CMakeLists.txt +++ b/llvm/unittests/Analysis/CMakeLists.txt @@ -6,7 +6,13 @@ set(LLVM_LINK_COMPONENTS TransformUtils ) -add_llvm_unittest(AnalysisTests +if (DEFINED LLVM_HAVE_TF_API) + LIST(APPEND EXTRA_TESTS TFUtilsTest.cpp) +else() + LIST(APPEND LLVM_OPTIONAL_SOURCES TFUtilsTest.cpp) +endif() + +add_llvm_unittest_with_input_files(AnalysisTests AliasAnalysisTest.cpp AliasSetTrackerTest.cpp AssumeBundleQueriesTest.cpp @@ -22,6 +28,7 @@ add_llvm_unittest(AnalysisTests DomTreeUpdaterTest.cpp GlobalsModRefTest.cpp InlineFeaturesAnalysisTest.cpp + InlineSizeEstimatorAnalysisTest.cpp IVDescriptorsTest.cpp LazyCallGraphTest.cpp LoadsTest.cpp @@ -40,4 +47,7 @@ add_llvm_unittest(AnalysisTests ValueLatticeTest.cpp ValueTrackingTest.cpp VectorUtilsTest.cpp + ${EXTRA_TESTS} ) + + target_link_libraries(AnalysisTests PRIVATE LLVMTestingSupport) diff --git a/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp b/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp new file mode 100644 index 0000000000000..377590be016ac --- /dev/null +++ b/llvm/unittests/Analysis/InlineSizeEstimatorAnalysisTest.cpp @@ -0,0 +1,101 @@ +//===- InlineSizeEstimatorAnalysisTest.cpp - test for ir2native -----------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/InlineSizeEstimatorAnalysis.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Testing/Support/SupportHelpers.h" +#include "gtest/gtest.h" + +using namespace llvm; + +extern const char *TestMainArgv0; +extern cl::opt TFIR2NativeModelPath; + +#if LLVM_HAVE_TF_API +static std::string getModelPath() { + SmallString<128> InputsDir = unittest::getInputFileDirectory(TestMainArgv0); + llvm::sys::path::append(InputsDir, "ir2native_x86_64_model"); + return std::string(InputsDir); +} +#endif + +static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { + SMDiagnostic Err; + std::unique_ptr Mod = parseAssemblyString(IR, Err, C); + if (!Mod) + Err.print("MLAnalysisTests", errs()); + return Mod; +} + +static FunctionAnalysisManager buildFAM() { + FunctionAnalysisManager FAM; + FAM.registerPass([&] { return DominatorTreeAnalysis(); }); + FAM.registerPass([&] { return PassInstrumentationAnalysis(); }); + FAM.registerPass([&] { return TargetIRAnalysis(); }); + FAM.registerPass([&] { return LoopAnalysis(); }); + return FAM; +} + +// Test model loading and evaluation. +TEST(InlineSizeEstimatorAnalysis, SizeIsValidTest) { + LLVMContext C; + std::unique_ptr M = parseIR(C, + R"IR( +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +declare i32 @f1(i32) +declare i32 @f2(i32) + +define i32 @branches(i32) { + %cond = icmp slt i32 %0, 3 + br i1 %cond, label %then, label %else + +then: + %ret.1 = call i32 @f1(i32 %0) + br label %last.block + +else: + %ret.2 = call i32 @f2(i32 %0) + br label %last.block + +last.block: + %ret = phi i32 [%ret.1, %then], [%ret.2, %else] + ret i32 %ret +} + +define internal i32 @top() { + %1 = call i32 @branches(i32 2) + %2 = call i32 @f1(i32 %1) + ret i32 %2 +} +)IR"); + + FunctionAnalysisManager FAM = buildFAM(); +#if LLVM_HAVE_TF_API + TFIR2NativeModelPath = getModelPath(); +#endif + + InlineSizeEstimatorAnalysis FA; + auto SizeEstimate = FA.run(*M->getFunction("branches"), FAM); +#if LLVM_HAVE_TF_API + EXPECT_GT(*SizeEstimate, 0); +#else + EXPECT_FALSE(SizeEstimate.hasValue()); +#endif +} diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt new file mode 100644 index 0000000000000..6efdad51083d3 --- /dev/null +++ b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/saved_model.pbtxt @@ -0,0 +1,10596 @@ +saved_model_schema_version: 1 +meta_graphs { + meta_info_def { + stripped_op_list { + op { + name: "Const" + output_arg { + name: "output" + type_attr: "dtype" + } + attr { + name: "value" + type: "tensor" + } + attr { + name: "dtype" + type: "type" + } + } + op { + name: "NoOp" + } + op { + name: "Placeholder" + output_arg { + name: "output" + type_attr: "dtype" + } + attr { + name: "dtype" + type: "type" + } + attr { + name: "shape" + type: "shape" + default_value { + shape { + unknown_rank: true + } + } + } + } + op { + name: "ReadVariableOp" + input_arg { + name: "resource" + type: DT_RESOURCE + } + output_arg { + name: "value" + type_attr: "dtype" + } + attr { + name: "dtype" + type: "type" + } + is_stateful: true + } + op { + name: "StatefulPartitionedCall" + input_arg { + name: "args" + type_list_attr: "Tin" + } + output_arg { + name: "output" + type_list_attr: "Tout" + } + attr { + name: "Tin" + type: "list(type)" + has_minimum: true + } + attr { + name: "Tout" + type: "list(type)" + has_minimum: true + } + attr { + name: "f" + type: "func" + } + attr { + name: "config" + type: "string" + default_value { + s: "" + } + } + attr { + name: "config_proto" + type: "string" + default_value { + s: "" + } + } + attr { + name: "executor_type" + type: "string" + default_value { + s: "" + } + } + is_stateful: true + } + op { + name: "VarHandleOp" + output_arg { + name: "resource" + type: DT_RESOURCE + } + attr { + name: "container" + type: "string" + default_value { + s: "" + } + } + attr { + name: "shared_name" + type: "string" + default_value { + s: "" + } + } + attr { + name: "dtype" + type: "type" + } + attr { + name: "shape" + type: "shape" + } + is_stateful: true + } + } + tags: "serve" + tensorflow_version: "1.15.0" + tensorflow_git_version: "unknown" + stripped_default_attrs: true + } + graph_def { + node { + name: "dense/kernel" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + } + } + attr { + key: "shared_name" + value { + s: "dense/kernel" + } + } + } + node { + name: "dense/kernel/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "dense/kernel" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "dense/bias" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 100 + } + } + } + } + attr { + key: "shared_name" + value { + s: "dense/bias" + } + } + } + node { + name: "dense/bias/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "dense/bias" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "dense_1/kernel" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + } + } + attr { + key: "shared_name" + value { + s: "dense_1/kernel" + } + } + } + node { + name: "dense_1/kernel/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_1/kernel" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "dense_1/bias" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + dim { + size: 1 + } + } + } + } + attr { + key: "shared_name" + value { + s: "dense_1/bias" + } + } + } + node { + name: "dense_1/bias/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_1/bias" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "total" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + } + } + } + attr { + key: "shared_name" + value { + s: "total" + } + } + } + node { + name: "total/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "total" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "count" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + } + } + } + attr { + key: "shared_name" + value { + s: "count" + } + } + } + node { + name: "count/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "count" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "total_1" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + } + } + } + attr { + key: "shared_name" + value { + s: "total_1" + } + } + } + node { + name: "total_1/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "total_1" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "count_1" + op: "VarHandleOp" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + attr { + key: "shape" + value { + shape { + } + } + } + attr { + key: "shared_name" + value { + s: "count_1" + } + } + } + node { + name: "count_1/Read/ReadVariableOp" + op: "ReadVariableOp" + input: "count_1" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + } + node { + name: "NoOp" + op: "NoOp" + } + node { + name: "Const" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + } + string_val: "\n\277\001\n\030\010\001\022\024layer_with_weights-0\n\013\010\001\022\007layer-0\n\030\010\002\022\024layer_with_weights-1\n\013\010\002\022\007layer-1\n\r\010\003\022\toptimizer\n\031\010\004\022\025regularization_losses\n\r\010\005\022\tvariables\n\027\010\006\022\023trainable_variables\n\r\010\007\022\tkeras_api\n\016\010\010\022\nsignatures\nh\n\n\010\t\022\006kernel\n\010\010\n\022\004bias\n\031\010\013\022\025regularization_losses\n\r\010\014\022\tvariables\n\027\010\r\022\023trainable_variables\n\r\010\016\022\tkeras_api\nh\n\n\010\017\022\006kernel\n\010\010\020\022\004bias\n\031\010\021\022\025regularization_losses\n\r\010\022\022\tvariables\n\027\010\023\022\023trainable_variables\n\r\010\024\022\tkeras_api\n\000\n\000\n\034\n\005\010\t\022\0010\n\005\010\n\022\0011\n\005\010\017\022\0012\n\005\010\020\022\0013\n\034\n\005\010\t\022\0010\n\005\010\n\022\0011\n\005\010\017\022\0012\n\005\010\020\022\0013\n\255\001\n\n\010\025\022\006layers\n\037\010\026\022\033layer_regularization_losses\n\033\010\027\022\027non_trainable_variables\n\021\010\030\022\rlayer_metrics\n\031\010\004\022\025regularization_losses\n\013\010\031\022\007metrics\n\r\010\005\022\tvariables\n\027\010\006\022\023trainable_variables\n\000\nX\022V\n\016VARIABLE_VALUE\022\014dense/kernel\0326layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE\nT\022R\n\016VARIABLE_VALUE\022\ndense/bias\0324layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010\t\022\0010\n\005\010\n\022\0011\n\016\n\005\010\t\022\0010\n\005\010\n\022\0011\n\255\001\n\n\010\032\022\006layers\n\037\010\033\022\033layer_regularization_losses\n\033\010\034\022\027non_trainable_variables\n\021\010\035\022\rlayer_metrics\n\031\010\013\022\025regularization_losses\n\013\010\036\022\007metrics\n\r\010\014\022\tvariables\n\027\010\r\022\023trainable_variables\nZ\022X\n\016VARIABLE_VALUE\022\016dense_1/kernel\0326layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE\nV\022T\n\016VARIABLE_VALUE\022\014dense_1/bias\0324layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010\017\022\0010\n\005\010\020\022\0011\n\016\n\005\010\017\022\0010\n\005\010\020\022\0011\n\255\001\n\n\010\037\022\006layers\n\037\010 \022\033layer_regularization_losses\n\033\010!\022\027non_trainable_variables\n\021\010\"\022\rlayer_metrics\n\031\010\021\022\025regularization_losses\n\013\010#\022\007metrics\n\r\010\022\022\tvariables\n\027\010\023\022\023trainable_variables\n\016\n\005\010\001\022\0010\n\005\010\002\022\0011\n\000\n\000\n\000\n\016\n\005\010$\022\0010\n\005\010%\022\0011\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n\000\n4\n\t\010&\022\005total\n\t\010\'\022\005count\n\r\010(\022\tvariables\n\r\010)\022\tkeras_api\nD\n\t\010*\022\005total\n\t\010+\022\005count\n\016\010,\022\n_fn_kwargs\n\r\010-\022\tvariables\n\r\010.\022\tkeras_api\nO\022M\n\016VARIABLE_VALUE\022\005total\0324keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE\nO\022M\n\016VARIABLE_VALUE\022\005count\0324keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE\n\016\n\005\010&\022\0010\n\005\010\'\022\0011\n\017\n\r\010(\022\tvariables\nQ\022O\n\016VARIABLE_VALUE\022\007total_1\0324keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE\nQ\022O\n\016VARIABLE_VALUE\022\007count_1\0324keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE\n\000\n\016\n\005\010*\022\0010\n\005\010+\022\0011\n\017\n\r\010-\022\tvariables" + } + } + } + } + node { + name: "serving_default_input_1" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "shape" + value { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + node { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "serving_default_input_1" + input: "dense/kernel" + input: "dense/bias" + input: "dense_1/kernel" + input: "dense_1/bias" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + i: 3 + i: 4 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_signature_wrapper_6671" + } + } + } + } + node { + name: "saver_filename" + op: "Placeholder" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "shape" + value { + shape { + } + } + } + } + node { + name: "StatefulPartitionedCall_1" + op: "StatefulPartitionedCall" + input: "saver_filename" + input: "dense/kernel/Read/ReadVariableOp" + input: "dense/bias/Read/ReadVariableOp" + input: "dense_1/kernel/Read/ReadVariableOp" + input: "dense_1/bias/Read/ReadVariableOp" + input: "total/Read/ReadVariableOp" + input: "count/Read/ReadVariableOp" + input: "total_1/Read/ReadVariableOp" + input: "count_1/Read/ReadVariableOp" + input: "Const" + attr { + key: "Tin" + value { + list { + type: DT_STRING + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_STRING + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_STRING + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference__traced_save_6824" + } + } + } + } + node { + name: "StatefulPartitionedCall_2" + op: "StatefulPartitionedCall" + input: "saver_filename" + input: "dense/kernel" + input: "dense/bias" + input: "dense_1/kernel" + input: "dense_1/bias" + input: "total" + input: "count" + input: "total_1" + input: "count_1" + attr { + key: "Tin" + value { + list { + type: DT_STRING + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_STRING + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference__traced_restore_6860" + } + } + } + } + library { + function { + signature { + name: "__inference__traced_restore_6860" + input_arg { + name: "file_prefix" + type: DT_STRING + } + input_arg { + name: "assignvariableop_dense_kernel" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_1_dense_bias" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_2_dense_1_kernel" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_3_dense_1_bias" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_4_total" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_5_count" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_6_total_1" + type: DT_RESOURCE + } + input_arg { + name: "assignvariableop_7_count_1" + type: DT_RESOURCE + } + output_arg { + name: "identity_9" + type: DT_STRING + } + is_stateful: true + control_output: "AssignVariableOp" + control_output: "AssignVariableOp_1" + control_output: "AssignVariableOp_2" + control_output: "AssignVariableOp_3" + control_output: "AssignVariableOp_4" + control_output: "AssignVariableOp_5" + control_output: "AssignVariableOp_6" + control_output: "AssignVariableOp_7" + control_output: "RestoreV2" + control_output: "RestoreV2_1" + } + node_def { + name: "RestoreV2/tensor_names" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 8 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 8 + } + } + string_val: "layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE" + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2/tensor_names" + } + } + node_def { + name: "RestoreV2/shape_and_slices" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 8 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 8 + } + } + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2/shape_and_slices" + } + } + node_def { + name: "RestoreV2" + op: "RestoreV2" + input: "file_prefix" + input: "RestoreV2/tensor_names:output:0" + input: "RestoreV2/shape_and_slices:output:0" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + attr { + key: "dtypes" + value { + list { + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "RestoreV2:tensors:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + node_def { + name: "AssignVariableOp" + op: "AssignVariableOp" + input: "assignvariableop_dense_kernel" + input: "Identity:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp" + } + } + node_def { + name: "Identity_1" + op: "Identity" + input: "RestoreV2:tensors:1" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_1" + } + } + node_def { + name: "AssignVariableOp_1" + op: "AssignVariableOp" + input: "assignvariableop_1_dense_bias" + input: "Identity_1:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_1" + } + } + node_def { + name: "Identity_2" + op: "Identity" + input: "RestoreV2:tensors:2" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_2" + } + } + node_def { + name: "AssignVariableOp_2" + op: "AssignVariableOp" + input: "assignvariableop_2_dense_1_kernel" + input: "Identity_2:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_2" + } + } + node_def { + name: "Identity_3" + op: "Identity" + input: "RestoreV2:tensors:3" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_3" + } + } + node_def { + name: "AssignVariableOp_3" + op: "AssignVariableOp" + input: "assignvariableop_3_dense_1_bias" + input: "Identity_3:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_3" + } + } + node_def { + name: "Identity_4" + op: "Identity" + input: "RestoreV2:tensors:4" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_4" + } + } + node_def { + name: "AssignVariableOp_4" + op: "AssignVariableOp" + input: "assignvariableop_4_total" + input: "Identity_4:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_4" + } + } + node_def { + name: "Identity_5" + op: "Identity" + input: "RestoreV2:tensors:5" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_5" + } + } + node_def { + name: "AssignVariableOp_5" + op: "AssignVariableOp" + input: "assignvariableop_5_count" + input: "Identity_5:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_5" + } + } + node_def { + name: "Identity_6" + op: "Identity" + input: "RestoreV2:tensors:6" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_6" + } + } + node_def { + name: "AssignVariableOp_6" + op: "AssignVariableOp" + input: "assignvariableop_6_total_1" + input: "Identity_6:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_6" + } + } + node_def { + name: "Identity_7" + op: "Identity" + input: "RestoreV2:tensors:7" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_7" + } + } + node_def { + name: "AssignVariableOp_7" + op: "AssignVariableOp" + input: "assignvariableop_7_count_1" + input: "Identity_7:output:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "AssignVariableOp_7" + } + } + node_def { + name: "RestoreV2_1/tensor_names" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 1 + } + } + string_val: "_CHECKPOINTABLE_OBJECT_GRAPH" + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2_1/tensor_names" + } + } + node_def { + name: "RestoreV2_1/shape_and_slices" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 1 + } + } + string_val: "" + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2_1/shape_and_slices" + } + } + node_def { + name: "RestoreV2_1" + op: "RestoreV2" + input: "file_prefix" + input: "RestoreV2_1/tensor_names:output:0" + input: "RestoreV2_1/shape_and_slices:output:0" + input: "^RestoreV2" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + unknown_rank: true + } + } + } + } + attr { + key: "dtypes" + value { + list { + type: DT_STRING + } + } + } + experimental_debug_info { + original_node_names: "RestoreV2_1" + } + } + node_def { + name: "NoOp" + op: "NoOp" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + experimental_debug_info { + original_node_names: "NoOp" + } + } + node_def { + name: "Identity_8" + op: "Identity" + input: "file_prefix" + input: "^AssignVariableOp" + input: "^AssignVariableOp_1" + input: "^AssignVariableOp_2" + input: "^AssignVariableOp_3" + input: "^AssignVariableOp_4" + input: "^AssignVariableOp_5" + input: "^AssignVariableOp_6" + input: "^AssignVariableOp_7" + input: "^NoOp" + device: "/device:CPU:0" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_8" + } + } + node_def { + name: "Identity_9" + op: "Identity" + input: "Identity_8:output:0" + input: "^AssignVariableOp" + input: "^AssignVariableOp_1" + input: "^AssignVariableOp_2" + input: "^AssignVariableOp_3" + input: "^AssignVariableOp_4" + input: "^AssignVariableOp_5" + input: "^AssignVariableOp_6" + input: "^AssignVariableOp_7" + input: "^RestoreV2" + input: "^RestoreV2_1" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_9" + } + } + ret { + key: "identity_9" + value: "Identity_9:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "AssignVariableOp" + value: "AssignVariableOp" + } + control_ret { + key: "AssignVariableOp_1" + value: "AssignVariableOp_1" + } + control_ret { + key: "AssignVariableOp_2" + value: "AssignVariableOp_2" + } + control_ret { + key: "AssignVariableOp_3" + value: "AssignVariableOp_3" + } + control_ret { + key: "AssignVariableOp_4" + value: "AssignVariableOp_4" + } + control_ret { + key: "AssignVariableOp_5" + value: "AssignVariableOp_5" + } + control_ret { + key: "AssignVariableOp_6" + value: "AssignVariableOp_6" + } + control_ret { + key: "AssignVariableOp_7" + value: "AssignVariableOp_7" + } + control_ret { + key: "RestoreV2" + value: "RestoreV2" + } + control_ret { + key: "RestoreV2_1" + value: "RestoreV2_1" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "file_prefix" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_fn_6629" + input_arg { + name: "input_1" + type: DT_INT32 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "input_1" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + i: 3 + i: 4 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6618" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "input_1" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6587" + input_arg { + name: "input_1" + type: DT_INT32 + } + input_arg { + name: "dense_6555" + type: DT_RESOURCE + } + input_arg { + name: "dense_6557" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_6581" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_6583" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "dense/StatefulPartitionedCall" + control_output: "dense_1/StatefulPartitionedCall" + } + node_def { + name: "dense/StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "input_1" + input: "dense_6555" + input: "dense_6557" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_layer_call_and_return_conditional_losses_6544" + } + } + } + experimental_debug_info { + original_node_names: "dense/StatefulPartitionedCall" + } + } + node_def { + name: "dense_1/StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "dense/StatefulPartitionedCall:output:0" + input: "dense_1_6581" + input: "dense_1_6583" + attr { + key: "Tin" + value { + list { + type: DT_FLOAT + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" + } + } + } + experimental_debug_info { + original_node_names: "dense_1/StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "dense_1/StatefulPartitionedCall:output:0" + input: "^dense/StatefulPartitionedCall" + input: "^dense_1/StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "dense/StatefulPartitionedCall" + value: "dense/StatefulPartitionedCall" + } + control_ret { + key: "dense_1/StatefulPartitionedCall" + value: "dense_1/StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "input_1" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6618" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "dense_6607" + type: DT_RESOURCE + } + input_arg { + name: "dense_6609" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_6612" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_6614" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "dense/StatefulPartitionedCall" + control_output: "dense_1/StatefulPartitionedCall" + } + node_def { + name: "dense/StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "inputs" + input: "dense_6607" + input: "dense_6609" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_layer_call_and_return_conditional_losses_6544" + } + } + } + experimental_debug_info { + original_node_names: "dense/StatefulPartitionedCall" + } + } + node_def { + name: "dense_1/StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "dense/StatefulPartitionedCall:output:0" + input: "dense_1_6612" + input: "dense_1_6614" + attr { + key: "Tin" + value { + list { + type: DT_FLOAT + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" + } + } + } + experimental_debug_info { + original_node_names: "dense_1/StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "dense_1/StatefulPartitionedCall:output:0" + input: "^dense/StatefulPartitionedCall" + input: "^dense_1/StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "dense/StatefulPartitionedCall" + value: "dense/StatefulPartitionedCall" + } + control_ret { + key: "dense_1/StatefulPartitionedCall" + value: "dense_1/StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_fn_6656" + input_arg { + name: "input_1" + type: DT_INT32 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "input_1" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + i: 3 + i: 4 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6645" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "input_1" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_dense_1_layer_call_and_return_conditional_losses_6764" + input_arg { + name: "inputs" + type: DT_FLOAT + } + input_arg { + name: "matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "biasadd_readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + } + node_def { + name: "MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "MatMul/ReadVariableOp" + } + } + node_def { + name: "MatMul" + op: "MatMul" + input: "inputs" + input: "MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "MatMul" + } + } + node_def { + name: "BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "BiasAdd/ReadVariableOp" + } + } + node_def { + name: "BiasAdd" + op: "BiasAdd" + input: "MatMul:product:0" + input: "BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "BiasAdd" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_dense_layer_call_fn_6754" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "inputs" + input: "unknown" + input: "unknown_0" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_layer_call_and_return_conditional_losses_6544" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference__traced_save_6824" + input_arg { + name: "file_prefix" + type: DT_STRING + } + input_arg { + name: "savev2_dense_kernel_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_dense_bias_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_dense_1_kernel_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_dense_1_bias_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_total_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_count_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_total_1_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_count_1_read_readvariableop" + type: DT_FLOAT + } + input_arg { + name: "savev2_1_const" + type: DT_STRING + } + output_arg { + name: "identity_1" + type: DT_STRING + } + is_stateful: true + control_output: "MergeV2Checkpoints" + control_output: "SaveV2" + control_output: "SaveV2_1" + } + node_def { + name: "StaticRegexFullMatch" + op: "StaticRegexFullMatch" + input: "file_prefix" + device: "/device:CPU:*" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "pattern" + value { + s: "^s3://.*" + } + } + experimental_debug_info { + original_node_names: "StaticRegexFullMatch" + } + } + node_def { + name: "Const" + op: "Const" + device: "/device:CPU:*" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + } + string_val: ".part" + } + } + } + experimental_debug_info { + original_node_names: "Const" + } + } + node_def { + name: "Const_1" + op: "Const" + device: "/device:CPU:*" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + } + string_val: "_temp_6f1e5fef49bb4c06ace07a8a95dfbb1b/part" + } + } + } + experimental_debug_info { + original_node_names: "Const_1" + } + } + node_def { + name: "Select" + op: "Select" + input: "StaticRegexFullMatch:output:0" + input: "Const:output:0" + input: "Const_1:output:0" + device: "/device:CPU:*" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Select" + } + } + node_def { + name: "StringJoin" + op: "StringJoin" + input: "file_prefix" + input: "Select:output:0" + device: "/device:CPU:*" + attr { + key: "N" + value { + i: 2 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "StringJoin" + } + } + node_def { + name: "num_shards" + op: "Const" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 2 + } + } + } + experimental_debug_info { + original_node_names: "num_shards" + } + } + node_def { + name: "ShardedFilename/shard" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 0 + } + } + } + experimental_debug_info { + original_node_names: "ShardedFilename/shard" + } + } + node_def { + name: "ShardedFilename" + op: "ShardedFilename" + input: "StringJoin:output:0" + input: "ShardedFilename/shard:output:0" + input: "num_shards:output:0" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "ShardedFilename" + } + } + node_def { + name: "SaveV2/tensor_names" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 8 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 8 + } + } + string_val: "layer_with_weights-0/kernel/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "layer_with_weights-0/bias/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "layer_with_weights-1/kernel/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "layer_with_weights-1/bias/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "keras_api/metrics/0/total/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "keras_api/metrics/0/count/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "keras_api/metrics/1/total/.ATTRIBUTES/VARIABLE_VALUE" + string_val: "keras_api/metrics/1/count/.ATTRIBUTES/VARIABLE_VALUE" + } + } + } + experimental_debug_info { + original_node_names: "SaveV2/tensor_names" + } + } + node_def { + name: "SaveV2/shape_and_slices" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 8 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 8 + } + } + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + string_val: "" + } + } + } + experimental_debug_info { + original_node_names: "SaveV2/shape_and_slices" + } + } + node_def { + name: "SaveV2" + op: "SaveV2" + input: "ShardedFilename:filename:0" + input: "SaveV2/tensor_names:output:0" + input: "SaveV2/shape_and_slices:output:0" + input: "savev2_dense_kernel_read_readvariableop" + input: "savev2_dense_bias_read_readvariableop" + input: "savev2_dense_1_kernel_read_readvariableop" + input: "savev2_dense_1_bias_read_readvariableop" + input: "savev2_total_read_readvariableop" + input: "savev2_count_read_readvariableop" + input: "savev2_total_1_read_readvariableop" + input: "savev2_count_1_read_readvariableop" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtypes" + value { + list { + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + type: DT_FLOAT + } + } + } + experimental_debug_info { + original_node_names: "SaveV2" + } + } + node_def { + name: "ShardedFilename_1/shard" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "dtype" + value { + type: DT_INT32 + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_INT32 + tensor_shape { + } + int_val: 1 + } + } + } + experimental_debug_info { + original_node_names: "ShardedFilename_1/shard" + } + } + node_def { + name: "ShardedFilename_1" + op: "ShardedFilename" + input: "StringJoin:output:0" + input: "ShardedFilename_1/shard:output:0" + input: "num_shards:output:0" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "ShardedFilename_1" + } + } + node_def { + name: "SaveV2_1/tensor_names" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 1 + } + } + string_val: "_CHECKPOINTABLE_OBJECT_GRAPH" + } + } + } + experimental_debug_info { + original_node_names: "SaveV2_1/tensor_names" + } + } + node_def { + name: "SaveV2_1/shape_and_slices" + op: "Const" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_STRING + } + } + attr { + key: "value" + value { + tensor { + dtype: DT_STRING + tensor_shape { + dim { + size: 1 + } + } + string_val: "" + } + } + } + experimental_debug_info { + original_node_names: "SaveV2_1/shape_and_slices" + } + } + node_def { + name: "SaveV2_1" + op: "SaveV2" + input: "ShardedFilename_1:filename:0" + input: "SaveV2_1/tensor_names:output:0" + input: "SaveV2_1/shape_and_slices:output:0" + input: "savev2_1_const" + input: "^SaveV2" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + attr { + key: "dtypes" + value { + list { + type: DT_STRING + } + } + } + experimental_debug_info { + original_node_names: "SaveV2_1" + } + } + node_def { + name: "MergeV2Checkpoints/checkpoint_prefixes" + op: "Pack" + input: "ShardedFilename:filename:0" + input: "ShardedFilename_1:filename:0" + input: "^SaveV2" + input: "^SaveV2_1" + device: "/device:CPU:0" + attr { + key: "N" + value { + i: 2 + } + } + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 2 + } + } + } + } + } + experimental_debug_info { + original_node_names: "MergeV2Checkpoints/checkpoint_prefixes" + } + } + node_def { + name: "MergeV2Checkpoints" + op: "MergeV2Checkpoints" + input: "MergeV2Checkpoints/checkpoint_prefixes:output:0" + input: "file_prefix" + input: "^SaveV2_1" + device: "/device:CPU:0" + attr { + key: "_output_shapes" + value { + list { + } + } + } + experimental_debug_info { + original_node_names: "MergeV2Checkpoints" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "file_prefix" + input: "^MergeV2Checkpoints" + device: "/device:CPU:0" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + node_def { + name: "Identity_1" + op: "Identity" + input: "Identity:output:0" + input: "^MergeV2Checkpoints" + input: "^SaveV2" + input: "^SaveV2_1" + attr { + key: "T" + value { + type: DT_STRING + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + experimental_debug_info { + original_node_names: "Identity_1" + } + } + ret { + key: "identity_1" + value: "Identity_1:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + } + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + shape { + dim { + size: 100 + } + } + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + shape { + dim { + size: 1 + } + } + shape { + } + shape { + } + shape { + } + shape { + } + shape { + } + } + } + } + control_ret { + key: "MergeV2Checkpoints" + value: "MergeV2Checkpoints" + } + control_ret { + key: "SaveV2" + value: "SaveV2" + } + control_ret { + key: "SaveV2_1" + value: "SaveV2_1" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "file_prefix" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + } + } + arg_attr { + key: 5 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 6 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 7 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 8 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 9 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6689" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "dense_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "dense_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + } + node_def { + name: "dense/Cast" + op: "Cast" + input: "inputs" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense/Cast" + } + } + node_def { + name: "dense/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "dense/MatMul/ReadVariableOp" + } + } + node_def { + name: "dense/MatMul" + op: "MatMul" + input: "dense/Cast:y:0" + input: "dense/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense/MatMul" + } + } + node_def { + name: "dense/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "dense/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "dense/BiasAdd" + op: "BiasAdd" + input: "dense/MatMul:product:0" + input: "dense/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense/BiasAdd" + } + } + node_def { + name: "dense/Relu" + op: "Relu" + input: "dense/BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense/Relu" + } + } + node_def { + name: "dense_1/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_1_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "dense_1/MatMul/ReadVariableOp" + } + } + node_def { + name: "dense_1/MatMul" + op: "MatMul" + input: "dense/Relu:activations:0" + input: "dense_1/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense_1/MatMul" + } + } + node_def { + name: "dense_1/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_1_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "dense_1/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "dense_1/BiasAdd" + op: "BiasAdd" + input: "dense_1/MatMul:product:0" + input: "dense_1/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense_1/BiasAdd" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "dense_1/BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_dense_layer_call_and_return_conditional_losses_6745" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "biasadd_readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + } + node_def { + name: "Cast" + op: "Cast" + input: "inputs" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Cast" + } + } + node_def { + name: "MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "MatMul/ReadVariableOp" + } + } + node_def { + name: "MatMul" + op: "MatMul" + input: "Cast:y:0" + input: "MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "MatMul" + } + } + node_def { + name: "BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "BiasAdd/ReadVariableOp" + } + } + node_def { + name: "BiasAdd" + op: "BiasAdd" + input: "MatMul:product:0" + input: "BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "BiasAdd" + } + } + node_def { + name: "Relu" + op: "Relu" + input: "BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Relu" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "Relu:activations:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_dense_1_layer_call_fn_6773" + input_arg { + name: "inputs" + type: DT_FLOAT + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "inputs" + input: "unknown" + input: "unknown_0" + attr { + key: "Tin" + value { + list { + type: DT_FLOAT + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference__wrapped_model_6528" + input_arg { + name: "input_1" + type: DT_INT32 + } + input_arg { + name: "sequential_dense_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "sequential_dense_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "sequential_dense_1_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "sequential_dense_1_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + } + node_def { + name: "sequential/dense/Cast" + op: "Cast" + input: "input_1" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + experimental_debug_info { + original_node_names: "sequential/dense/Cast" + } + } + node_def { + name: "sequential/dense/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "sequential_dense_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "sequential/dense/MatMul/ReadVariableOp" + } + } + node_def { + name: "sequential/dense/MatMul" + op: "MatMul" + input: "sequential/dense/Cast:y:0" + input: "sequential/dense/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "sequential/dense/MatMul" + } + } + node_def { + name: "sequential/dense/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "sequential_dense_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "sequential/dense/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "sequential/dense/BiasAdd" + op: "BiasAdd" + input: "sequential/dense/MatMul:product:0" + input: "sequential/dense/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "sequential/dense/BiasAdd" + } + } + node_def { + name: "sequential/dense/Relu" + op: "Relu" + input: "sequential/dense/BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "sequential/dense/Relu" + } + } + node_def { + name: "sequential/dense_1/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "sequential_dense_1_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "sequential/dense_1/MatMul/ReadVariableOp" + } + } + node_def { + name: "sequential/dense_1/MatMul" + op: "MatMul" + input: "sequential/dense/Relu:activations:0" + input: "sequential/dense_1/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "sequential/dense_1/MatMul" + } + } + node_def { + name: "sequential/dense_1/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "sequential_dense_1_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "sequential/dense_1/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "sequential/dense_1/BiasAdd" + op: "BiasAdd" + input: "sequential/dense_1/MatMul:product:0" + input: "sequential/dense_1/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "sequential/dense_1/BiasAdd" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "sequential/dense_1/BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "input_1" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_dense_layer_call_and_return_conditional_losses_6544" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "biasadd_readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + } + node_def { + name: "Cast" + op: "Cast" + input: "inputs" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Cast" + } + } + node_def { + name: "MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "MatMul/ReadVariableOp" + } + } + node_def { + name: "MatMul" + op: "MatMul" + input: "Cast:y:0" + input: "MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "MatMul" + } + } + node_def { + name: "BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "BiasAdd/ReadVariableOp" + } + } + node_def { + name: "BiasAdd" + op: "BiasAdd" + input: "MatMul:product:0" + input: "BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "BiasAdd" + } + } + node_def { + name: "Relu" + op: "Relu" + input: "BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Relu" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "Relu:activations:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6601" + input_arg { + name: "input_1" + type: DT_INT32 + } + input_arg { + name: "dense_6590" + type: DT_RESOURCE + } + input_arg { + name: "dense_6592" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_6595" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_6597" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "dense/StatefulPartitionedCall" + control_output: "dense_1/StatefulPartitionedCall" + } + node_def { + name: "dense/StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "input_1" + input: "dense_6590" + input: "dense_6592" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_layer_call_and_return_conditional_losses_6544" + } + } + } + experimental_debug_info { + original_node_names: "dense/StatefulPartitionedCall" + } + } + node_def { + name: "dense_1/StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "dense/StatefulPartitionedCall:output:0" + input: "dense_1_6595" + input: "dense_1_6597" + attr { + key: "Tin" + value { + list { + type: DT_FLOAT + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" + } + } + } + experimental_debug_info { + original_node_names: "dense_1/StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "dense_1/StatefulPartitionedCall:output:0" + input: "^dense/StatefulPartitionedCall" + input: "^dense_1/StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "dense/StatefulPartitionedCall" + value: "dense/StatefulPartitionedCall" + } + control_ret { + key: "dense_1/StatefulPartitionedCall" + value: "dense_1/StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "input_1" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_fn_6733" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "inputs" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + i: 3 + i: 4 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6645" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6645" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "dense_6634" + type: DT_RESOURCE + } + input_arg { + name: "dense_6636" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_6639" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_6641" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "dense/StatefulPartitionedCall" + control_output: "dense_1/StatefulPartitionedCall" + } + node_def { + name: "dense/StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "inputs" + input: "dense_6634" + input: "dense_6636" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_layer_call_and_return_conditional_losses_6544" + } + } + } + experimental_debug_info { + original_node_names: "dense/StatefulPartitionedCall" + } + } + node_def { + name: "dense_1/StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "dense/StatefulPartitionedCall:output:0" + input: "dense_1_6639" + input: "dense_1_6641" + attr { + key: "Tin" + value { + list { + type: DT_FLOAT + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" + } + } + } + experimental_debug_info { + original_node_names: "dense_1/StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "dense_1/StatefulPartitionedCall:output:0" + input: "^dense/StatefulPartitionedCall" + input: "^dense_1/StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "dense/StatefulPartitionedCall" + value: "dense/StatefulPartitionedCall" + } + control_ret { + key: "dense_1/StatefulPartitionedCall" + value: "dense_1/StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_dense_1_layer_call_and_return_conditional_losses_6570" + input_arg { + name: "inputs" + type: DT_FLOAT + } + input_arg { + name: "matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "biasadd_readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + } + node_def { + name: "MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "MatMul/ReadVariableOp" + } + } + node_def { + name: "MatMul" + op: "MatMul" + input: "inputs" + input: "MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "MatMul" + } + } + node_def { + name: "BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "BiasAdd/ReadVariableOp" + } + } + node_def { + name: "BiasAdd" + op: "BiasAdd" + input: "MatMul:product:0" + input: "BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "BiasAdd" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_signature_wrapper_6671" + input_arg { + name: "input_1" + type: DT_INT32 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "input_1" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + i: 3 + i: 4 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference__wrapped_model_6528" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "input_1" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_fn_6720" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "unknown" + type: DT_RESOURCE + } + input_arg { + name: "unknown_0" + type: DT_RESOURCE + } + input_arg { + name: "unknown_1" + type: DT_RESOURCE + } + input_arg { + name: "unknown_2" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + control_output: "StatefulPartitionedCall" + } + node_def { + name: "StatefulPartitionedCall" + op: "StatefulPartitionedCall" + input: "inputs" + input: "unknown" + input: "unknown_0" + input: "unknown_1" + input: "unknown_2" + attr { + key: "Tin" + value { + list { + type: DT_INT32 + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + type: DT_RESOURCE + } + } + } + attr { + key: "Tout" + value { + list { + type: DT_FLOAT + } + } + } + attr { + key: "_collective_manager_ids" + value { + list { + } + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "_read_only_resource_inputs" + value { + list { + i: 1 + i: 2 + i: 3 + i: 4 + } + } + } + attr { + key: "config_proto" + value { + s: "\n\007\n\003CPU\020\001\n\007\n\003GPU\020\0002\002J\0008\001" + } + } + attr { + key: "f" + value { + func { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6618" + } + } + } + experimental_debug_info { + original_node_names: "StatefulPartitionedCall" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "StatefulPartitionedCall:output:0" + input: "^StatefulPartitionedCall" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + control_ret { + key: "StatefulPartitionedCall" + value: "StatefulPartitionedCall" + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + function { + signature { + name: "__inference_sequential_layer_call_and_return_conditional_losses_6707" + input_arg { + name: "inputs" + type: DT_INT32 + } + input_arg { + name: "dense_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "dense_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_matmul_readvariableop_resource" + type: DT_RESOURCE + } + input_arg { + name: "dense_1_biasadd_readvariableop_resource" + type: DT_RESOURCE + } + output_arg { + name: "identity" + type: DT_FLOAT + } + is_stateful: true + } + node_def { + name: "dense/Cast" + op: "Cast" + input: "inputs" + attr { + key: "DstT" + value { + type: DT_FLOAT + } + } + attr { + key: "SrcT" + value { + type: DT_INT32 + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense/Cast" + } + } + node_def { + name: "dense/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "dense/MatMul/ReadVariableOp" + } + } + node_def { + name: "dense/MatMul" + op: "MatMul" + input: "dense/Cast:y:0" + input: "dense/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense/MatMul" + } + } + node_def { + name: "dense/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "dense/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "dense/BiasAdd" + op: "BiasAdd" + input: "dense/MatMul:product:0" + input: "dense/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense/BiasAdd" + } + } + node_def { + name: "dense/Relu" + op: "Relu" + input: "dense/BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense/Relu" + } + } + node_def { + name: "dense_1/MatMul/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_1_matmul_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "dense_1/MatMul/ReadVariableOp" + } + } + node_def { + name: "dense_1/MatMul" + op: "MatMul" + input: "dense/Relu:activations:0" + input: "dense_1/MatMul/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense_1/MatMul" + } + } + node_def { + name: "dense_1/BiasAdd/ReadVariableOp" + op: "ReadVariableOp" + input: "dense_1_biasadd_readvariableop_resource" + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: 1 + } + } + } + } + } + attr { + key: "dtype" + value { + type: DT_FLOAT + } + } + experimental_debug_info { + original_node_names: "dense_1/BiasAdd/ReadVariableOp" + } + } + node_def { + name: "dense_1/BiasAdd" + op: "BiasAdd" + input: "dense_1/MatMul:product:0" + input: "dense_1/BiasAdd/ReadVariableOp:value:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "dense_1/BiasAdd" + } + } + node_def { + name: "Identity" + op: "Identity" + input: "dense_1/BiasAdd:output:0" + attr { + key: "T" + value { + type: DT_FLOAT + } + } + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + } + experimental_debug_info { + original_node_names: "Identity" + } + } + ret { + key: "identity" + value: "Identity:output:0" + } + attr { + key: "_input_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + shape { + unknown_rank: true + } + } + } + } + arg_attr { + key: 0 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + } + attr { + key: "_user_specified_name" + value { + s: "inputs" + } + } + } + } + arg_attr { + key: 1 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 2 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 3 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + arg_attr { + key: 4 + value { + attr { + key: "_output_shapes" + value { + list { + shape { + } + } + } + } + } + } + } + } + versions { + producer: 331 + min_consumer: 12 + } + } + saver_def { + filename_tensor_name: "saver_filename:0" + save_tensor_name: "StatefulPartitionedCall_1:0" + restore_op_name: "StatefulPartitionedCall_2" + version: V2 + } + collection_def { + key: "saved_model_main_op" + value { + node_list { + value: "NoOp" + } + } + } + signature_def { + key: "__saved_model_init_op" + value { + outputs { + key: "__saved_model_init_op" + value { + name: "NoOp" + tensor_shape { + unknown_rank: true + } + } + } + } + } + signature_def { + key: "serving_default" + value { + inputs { + key: "input_1" + value { + name: "serving_default_input_1:0" + dtype: DT_INT32 + tensor_shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + } + } + outputs { + key: "output_1" + value { + name: "StatefulPartitionedCall:0" + dtype: DT_FLOAT + tensor_shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + } + } + method_name: "tensorflow/serving/predict" + } + } + object_graph_def { + nodes { + children { + node_id: 1 + local_name: "layer_with_weights-0" + } + children { + node_id: 1 + local_name: "layer-0" + } + children { + node_id: 2 + local_name: "layer_with_weights-1" + } + children { + node_id: 2 + local_name: "layer-1" + } + children { + node_id: 3 + local_name: "optimizer" + } + children { + node_id: 4 + local_name: "regularization_losses" + } + children { + node_id: 5 + local_name: "variables" + } + children { + node_id: 6 + local_name: "trainable_variables" + } + children { + node_id: 7 + local_name: "keras_api" + } + children { + node_id: 8 + local_name: "signatures" + } + children { + node_id: 47 + local_name: "__call__" + } + children { + node_id: 48 + local_name: "_default_save_signature" + } + children { + node_id: 49 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_sequential" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Sequential\", \"name\": \"sequential\", \"trainable\": true, \"expects_training_arg\": true, \"dtype\": \"float32\", \"batch_input_shape\": null, \"config\": {\"name\": \"sequential\", \"layers\": [{\"class_name\": \"Dense\", \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}, {\"class_name\": \"Dense\", \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}], \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 214}}}, \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}, \"is_graph_network\": false, \"keras_version\": \"2.2.4-tf\", \"backend\": \"tensorflow\", \"model_config\": {\"class_name\": \"Sequential\", \"config\": {\"name\": \"sequential\", \"layers\": [{\"class_name\": \"Dense\", \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}, {\"class_name\": \"Dense\", \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}}], \"build_input_shape\": {\"class_name\": \"__tuple__\", \"items\": [null, 214]}}}, \"training_config\": {\"loss\": \"mean_absolute_error\", \"metrics\": [\"mean_squared_error\"], \"weighted_metrics\": null, \"loss_weights\": null, \"sample_weight_mode\": null, \"optimizer_config\": {\"class_name\": \"Adam\", \"config\": {\"name\": \"Adam\", \"learning_rate\": 0.0003000000142492354, \"decay\": 0.0, \"beta_1\": 0.8999999761581421, \"beta_2\": 0.9990000128746033, \"epsilon\": 1e-07, \"amsgrad\": false}}}}" + } + } + nodes { + children { + node_id: 9 + local_name: "kernel" + } + children { + node_id: 10 + local_name: "bias" + } + children { + node_id: 11 + local_name: "regularization_losses" + } + children { + node_id: 12 + local_name: "variables" + } + children { + node_id: 13 + local_name: "trainable_variables" + } + children { + node_id: 14 + local_name: "keras_api" + } + children { + node_id: 50 + local_name: "__call__" + } + children { + node_id: 51 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Dense\", \"name\": \"dense\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 100, \"activation\": \"relu\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 214}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [null, 214]}}" + } + } + nodes { + children { + node_id: 15 + local_name: "kernel" + } + children { + node_id: 16 + local_name: "bias" + } + children { + node_id: 17 + local_name: "regularization_losses" + } + children { + node_id: 18 + local_name: "variables" + } + children { + node_id: 19 + local_name: "trainable_variables" + } + children { + node_id: 20 + local_name: "keras_api" + } + children { + node_id: 52 + local_name: "__call__" + } + children { + node_id: 53 + local_name: "call_and_return_all_conditional_losses" + } + user_object { + identifier: "_tf_keras_layer" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Dense\", \"name\": \"dense_1\", \"trainable\": true, \"expects_training_arg\": false, \"dtype\": \"float32\", \"batch_input_shape\": null, \"stateful\": false, \"config\": {\"name\": \"dense_1\", \"trainable\": true, \"dtype\": \"float32\", \"units\": 1, \"activation\": \"linear\", \"use_bias\": true, \"kernel_initializer\": {\"class_name\": \"GlorotUniform\", \"config\": {\"seed\": null}}, \"bias_initializer\": {\"class_name\": \"Zeros\", \"config\": {}}, \"kernel_regularizer\": null, \"bias_regularizer\": null, \"activity_regularizer\": null, \"kernel_constraint\": null, \"bias_constraint\": null}, \"input_spec\": {\"class_name\": \"InputSpec\", \"config\": {\"dtype\": null, \"shape\": null, \"ndim\": null, \"max_ndim\": null, \"min_ndim\": 2, \"axes\": {\"-1\": 100}}}, \"build_input_shape\": {\"class_name\": \"TensorShape\", \"items\": [null, 100]}}" + } + } + nodes { + user_object { + identifier: "optimizer" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 9 + local_name: "0" + } + children { + node_id: 10 + local_name: "1" + } + children { + node_id: 15 + local_name: "2" + } + children { + node_id: 16 + local_name: "3" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 9 + local_name: "0" + } + children { + node_id: 10 + local_name: "1" + } + children { + node_id: 15 + local_name: "2" + } + children { + node_id: 16 + local_name: "3" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 21 + local_name: "layers" + } + children { + node_id: 22 + local_name: "layer_regularization_losses" + } + children { + node_id: 23 + local_name: "non_trainable_variables" + } + children { + node_id: 24 + local_name: "layer_metrics" + } + children { + node_id: 4 + local_name: "regularization_losses" + } + children { + node_id: 25 + local_name: "metrics" + } + children { + node_id: 5 + local_name: "variables" + } + children { + node_id: 6 + local_name: "trainable_variables" + } + children { + node_id: 47 + local_name: "__call__" + } + children { + node_id: 48 + local_name: "_default_save_signature" + } + children { + node_id: 49 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 49 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 54 + local_name: "serving_default" + } + user_object { + identifier: "signature_map" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 214 + } + dim { + size: 100 + } + } + trainable: true + name: "dense/kernel" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 100 + } + } + trainable: true + name: "dense/bias" + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 9 + local_name: "0" + } + children { + node_id: 10 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 9 + local_name: "0" + } + children { + node_id: 10 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 26 + local_name: "layers" + } + children { + node_id: 27 + local_name: "layer_regularization_losses" + } + children { + node_id: 28 + local_name: "non_trainable_variables" + } + children { + node_id: 29 + local_name: "layer_metrics" + } + children { + node_id: 11 + local_name: "regularization_losses" + } + children { + node_id: 30 + local_name: "metrics" + } + children { + node_id: 12 + local_name: "variables" + } + children { + node_id: 13 + local_name: "trainable_variables" + } + children { + node_id: 50 + local_name: "__call__" + } + children { + node_id: 51 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 51 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 100 + } + dim { + size: 1 + } + } + trainable: true + name: "dense_1/kernel" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + dim { + size: 1 + } + } + trainable: true + name: "dense_1/bias" + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 15 + local_name: "0" + } + children { + node_id: 16 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 15 + local_name: "0" + } + children { + node_id: 16 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 31 + local_name: "layers" + } + children { + node_id: 32 + local_name: "layer_regularization_losses" + } + children { + node_id: 33 + local_name: "non_trainable_variables" + } + children { + node_id: 34 + local_name: "layer_metrics" + } + children { + node_id: 17 + local_name: "regularization_losses" + } + children { + node_id: 35 + local_name: "metrics" + } + children { + node_id: 18 + local_name: "variables" + } + children { + node_id: 19 + local_name: "trainable_variables" + } + children { + node_id: 52 + local_name: "__call__" + } + children { + node_id: 53 + local_name: "call_and_return_all_conditional_losses" + } + children { + node_id: 53 + local_name: "call_and_return_conditional_losses" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 1 + local_name: "0" + } + children { + node_id: 2 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 36 + local_name: "0" + } + children { + node_id: 37 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 38 + local_name: "total" + } + children { + node_id: 39 + local_name: "count" + } + children { + node_id: 40 + local_name: "variables" + } + children { + node_id: 41 + local_name: "keras_api" + } + user_object { + identifier: "_tf_keras_metric" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"Mean\", \"name\": \"loss\", \"dtype\": \"float32\", \"config\": {\"name\": \"loss\", \"dtype\": \"float32\"}}" + } + } + nodes { + children { + node_id: 42 + local_name: "total" + } + children { + node_id: 43 + local_name: "count" + } + children { + node_id: 44 + local_name: "_fn_kwargs" + } + children { + node_id: 45 + local_name: "variables" + } + children { + node_id: 46 + local_name: "keras_api" + } + user_object { + identifier: "_tf_keras_metric" + version { + producer: 1 + min_consumer: 1 + } + metadata: "{\"class_name\": \"MeanMetricWrapper\", \"name\": \"mean_squared_error\", \"dtype\": \"float32\", \"config\": {\"name\": \"mean_squared_error\", \"dtype\": \"float32\", \"fn\": \"mean_squared_error\"}}" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + } + synchronization: VARIABLE_SYNCHRONIZATION_ON_READ + aggregation: VARIABLE_AGGREGATION_SUM + name: "total" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + } + synchronization: VARIABLE_SYNCHRONIZATION_ON_READ + aggregation: VARIABLE_AGGREGATION_SUM + name: "count" + } + } + nodes { + children { + node_id: 38 + local_name: "0" + } + children { + node_id: 39 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 40 + local_name: "variables" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + } + synchronization: VARIABLE_SYNCHRONIZATION_ON_READ + aggregation: VARIABLE_AGGREGATION_SUM + name: "total" + } + } + nodes { + variable { + dtype: DT_FLOAT + shape { + } + synchronization: VARIABLE_SYNCHRONIZATION_ON_READ + aggregation: VARIABLE_AGGREGATION_SUM + name: "count" + } + } + nodes { + user_object { + identifier: "trackable_dict_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 42 + local_name: "0" + } + children { + node_id: 43 + local_name: "1" + } + user_object { + identifier: "trackable_list_wrapper" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + children { + node_id: 45 + local_name: "variables" + } + user_object { + identifier: "_generic_user_object" + version { + producer: 1 + min_consumer: 1 + } + } + } + nodes { + function { + concrete_functions: "__inference_sequential_layer_call_fn_6629" + concrete_functions: "__inference_sequential_layer_call_fn_6733" + concrete_functions: "__inference_sequential_layer_call_fn_6720" + concrete_functions: "__inference_sequential_layer_call_fn_6656" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "training" + } + values { + string_value: "mask" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + bool_value: false + } + values { + none_value { + } + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + concrete_functions: "__inference__wrapped_model_6528" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + } + } + } + values { + key: "varargs" + value { + string_value: "args" + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + input_signature { + tuple_value { + values { + tensor_spec_value { + name: "input_1" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + } + } + } + } + } + nodes { + function { + concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6689" + concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6587" + concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6707" + concrete_functions: "__inference_sequential_layer_call_and_return_conditional_losses_6601" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + values { + string_value: "training" + } + values { + string_value: "mask" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + list_value { + values { + bool_value: false + } + values { + none_value { + } + } + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + dict_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + concrete_functions: "__inference_dense_layer_call_fn_6754" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + concrete_functions: "__inference_dense_layer_call_and_return_conditional_losses_6745" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + concrete_functions: "__inference_dense_1_layer_call_fn_6773" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + function { + concrete_functions: "__inference_dense_1_layer_call_and_return_conditional_losses_6764" + function_spec { + fullargspec { + named_tuple_value { + name: "FullArgSpec" + values { + key: "args" + value { + list_value { + values { + string_value: "self" + } + values { + string_value: "inputs" + } + } + } + } + values { + key: "varargs" + value { + none_value { + } + } + } + values { + key: "varkw" + value { + none_value { + } + } + } + values { + key: "defaults" + value { + none_value { + } + } + } + values { + key: "kwonlyargs" + value { + list_value { + } + } + } + values { + key: "kwonlydefaults" + value { + none_value { + } + } + } + values { + key: "annotations" + value { + dict_value { + } + } + } + } + } + is_method: true + input_signature { + none_value { + } + } + } + } + } + nodes { + bare_concrete_function { + concrete_function_name: "__inference_signature_wrapper_6671" + argument_keywords: "input_1" + allowed_positional_arguments: 1 + } + } + concrete_functions { + key: "__inference__wrapped_model_6528" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "input_1" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + dict_value { + fields { + key: "output_1" + value { + tensor_spec_value { + name: "output_1" + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + } + } + } + } + concrete_functions { + key: "__inference_dense_1_layer_call_and_return_conditional_losses_6764" + value { + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "inputs" + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + dtype: DT_FLOAT + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tuple_value { + values { + tensor_spec_value { + name: "0" + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + values { + list_value { + } + } + } + } + } + } + concrete_functions { + key: "__inference_dense_1_layer_call_fn_6773" + value { + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "inputs" + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + dtype: DT_FLOAT + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tensor_spec_value { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + } + concrete_functions { + key: "__inference_dense_layer_call_and_return_conditional_losses_6745" + value { + bound_inputs: 9 + bound_inputs: 10 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "inputs" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tuple_value { + values { + tensor_spec_value { + name: "0" + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + dtype: DT_FLOAT + } + } + values { + list_value { + } + } + } + } + } + } + concrete_functions { + key: "__inference_dense_layer_call_fn_6754" + value { + bound_inputs: 9 + bound_inputs: 10 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "inputs" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tensor_spec_value { + shape { + dim { + size: -1 + } + dim { + size: 100 + } + } + dtype: DT_FLOAT + } + } + } + } + concrete_functions { + key: "__inference_sequential_layer_call_and_return_conditional_losses_6587" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "input_1" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + values { + bool_value: true + } + values { + none_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tuple_value { + values { + tensor_spec_value { + name: "0" + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + values { + list_value { + } + } + } + } + } + } + concrete_functions { + key: "__inference_sequential_layer_call_and_return_conditional_losses_6601" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "input_1" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + values { + bool_value: false + } + values { + none_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tuple_value { + values { + tensor_spec_value { + name: "0" + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + values { + list_value { + } + } + } + } + } + } + concrete_functions { + key: "__inference_sequential_layer_call_and_return_conditional_losses_6689" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "inputs" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + values { + bool_value: true + } + values { + none_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tuple_value { + values { + tensor_spec_value { + name: "0" + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + values { + list_value { + } + } + } + } + } + } + concrete_functions { + key: "__inference_sequential_layer_call_and_return_conditional_losses_6707" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "inputs" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + values { + bool_value: false + } + values { + none_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tuple_value { + values { + tensor_spec_value { + name: "0" + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + values { + list_value { + } + } + } + } + } + } + concrete_functions { + key: "__inference_sequential_layer_call_fn_6629" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "input_1" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + values { + bool_value: true + } + values { + none_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tensor_spec_value { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + } + concrete_functions { + key: "__inference_sequential_layer_call_fn_6656" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "input_1" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + values { + bool_value: false + } + values { + none_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tensor_spec_value { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + } + concrete_functions { + key: "__inference_sequential_layer_call_fn_6720" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "inputs" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + values { + bool_value: true + } + values { + none_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tensor_spec_value { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + } + concrete_functions { + key: "__inference_sequential_layer_call_fn_6733" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + values { + tensor_spec_value { + name: "inputs" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + values { + bool_value: false + } + values { + none_value { + } + } + } + } + values { + dict_value { + } + } + } + } + output_signature { + tensor_spec_value { + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + } + concrete_functions { + key: "__inference_signature_wrapper_6671" + value { + bound_inputs: 9 + bound_inputs: 10 + bound_inputs: 15 + bound_inputs: 16 + canonicalized_input_signature { + tuple_value { + values { + tuple_value { + } + } + values { + dict_value { + fields { + key: "input_1" + value { + tensor_spec_value { + name: "input_1" + shape { + dim { + size: -1 + } + dim { + size: 214 + } + } + dtype: DT_INT32 + } + } + } + } + } + } + } + output_signature { + dict_value { + fields { + key: "output_1" + value { + tensor_spec_value { + name: "output_1" + shape { + dim { + size: -1 + } + dim { + size: 1 + } + } + dtype: DT_FLOAT + } + } + } + } + } + } + } + } +} + diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001 b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.data-00000-of-00001 new file mode 100644 index 0000000000000000000000000000000000000000..98807d26ee9f40e99330ae6a5d2988c640a320ec GIT binary patch literal 88424 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

+d4W!E+~y333|Hr9)dThX)0R^VOV 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%0D8?`HBcY!+5c|#2G|*uNPG9Q@ zKZjHk9kmT*=HD{r<4#f~MLjetTU7hEdofH92AD-K~!*X z?ZbEv-e8?Jd~Xw?_V*CY5{KdGE)K=*DYL?A56*Yc!CjjE=$1MIO=mgb>hX_hOw?nT zwnK#0Z8-_8U3KX9oFO~gu8|+T9E787sI}A2DO}YX~$k=SyQ`k$@A1tE@FP_kbN2XN3 z&Y&C04M?cjKAJP-3z0fMg%)foC2B)1^l9@*Y^k z=jlg0XU)ZL;)>94-G?rA4j>*+dPw(6Z=(3Yn3a3B0{)6mhGE``#)L&N3vUOb*^h1X zPK_5GJI$XfP~OhIcuW`{`!@3Mhz;#*)1~jHkFPuT$A_NYRzrGOd3xJ_8Eu}Mc=bt& z7Aj;UQ{`K>I61?SuHP5ScwbB5^-b=Aajsfj_lN?2elfw+=`M7~$4TtA`zMIlJ8{

3r8j?9kuMIsQx|%S`f^jW-*}C7X3% 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 !xswBeIdG!<4 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

9}7NmN#I%0%U{fvRdqTtD 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 z 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 literal 0 HcmV?d00001 diff --git a/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index b/llvm/unittests/Analysis/Inputs/ir2native_x86_64_model/variables/variables.index new file mode 100644 index 0000000000000000000000000000000000000000..c20d8afabf383430e807fde58270f4ff7c92fdc5 GIT binary patch literal 398 zcmbQn@*$OhfsKPviiv}fK}I0n*~8V@JHX%5FT~Nw$2H#H$;;I_B;Gy9F~Ea^U5G(p z%3@ZHEBvOMEJwl_O!%`?ixP|D6ALo+b5l!-GLwt-4fK=qOY=(f^&CS&f;^oGtXXkj%{$(r+6K}d<; zP(QgZje%hTs|n91pMdA{fb1StqZ*47qNWTcA~}hbsYUVSnI#$V<*AwJ870NK2Kq^v ziN$4W7!p{7m^e}t9?W6Yn80lMt3U99sG=CqrFp4UPZ%ONg_t?6F@jWR09BZFzuEp# zSW(z;RuKaSqe27g9*HtPHz83)iM~Pxph%7cP$i?nhxx2)b@qRrx`qJ=7(uw8ao InputsDir = unittest::getInputFileDirectory(TestMainArgv0); + llvm::sys::path::append(InputsDir, "ir2native_x86_64_model"); + return std::string(InputsDir); +} + +// Test observable behavior when no model is provided. +TEST(TFUtilsTest, NoModel) { + TFModelEvaluator Evaluator("", {}, {}); + EXPECT_FALSE(Evaluator.isValid()); +} + +// Test we can correctly load a savedmodel and evaluate it. +TEST(TFUtilsTest, LoadAndExecuteTest) { + // We use the ir2native model for test. We know it has one feature of + // dimension (1, 214) + std::vector InputNames{"serving_default_input_1"}; + std::vector OutputName{"StatefulPartitionedCall"}; + const static int64_t KnownSize = 214; + + TFModelEvaluator Evaluator(getModelPath(), InputNames, OutputName); + static const std::vector Dim{1, KnownSize}; + + EXPECT_TRUE(Evaluator.isValid()); + Evaluator.initInput(0, TF_INT32, Dim); + + int32_t *V = static_cast(TF_TensorData(Evaluator.getInput()[0])); + // Fill it up with 1's, we know the output. + for (auto I = 0; I < KnownSize; ++I) { + V[I] = 1; + } + { + auto ER = Evaluator.evaluate(); + EXPECT_TRUE(ER.hasValue()); + float Ret = *ER->getTensorValue(0); + EXPECT_EQ(static_cast(Ret), 80); + } + // The input vector should be unchanged + for (auto I = 0; I < KnownSize; ++I) { + EXPECT_EQ(V[I], 1); + } + // Zero-out the unused position '0' of the instruction histogram, which is + // after the first 9 calculated values. Should the the same result. + V[9] = 0; + { + auto ER = Evaluator.evaluate(); + EXPECT_TRUE(ER.hasValue()); + float Ret = *ER->getTensorValue(0); + EXPECT_EQ(static_cast(Ret), 80); + } +} + +// Test incorrect input setup +TEST(TFUtilsTest, EvalError) { + // We use the ir2native model for test. We know it has one feature of + // dimension (1, 214) + std::vector InputNames{"serving_default_input_1"}; + std::vector OutputName{"StatefulPartitionedCall"}; + const static int64_t KnownSize = 213; + + TFModelEvaluator Evaluator(getModelPath(), InputNames, OutputName); + static const std::vector Dim{1, KnownSize}; + + EXPECT_TRUE(Evaluator.isValid()); + Evaluator.initInput(0, TF_INT32, Dim); + + int32_t *V = static_cast(TF_TensorData(Evaluator.getInput()[0])); + // Fill it up with 1's, we know the output. + for (auto I = 0; I < KnownSize; ++I) { + V[I] = 1; + } + auto ER = Evaluator.evaluate(); + EXPECT_FALSE(ER.hasValue()); + EXPECT_FALSE(Evaluator.isValid()); +} From 73f02a61dfb967e3d058490b0c39178e1219835e Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Mon, 13 Jul 2020 16:29:19 -0700 Subject: [PATCH 174/771] [llvm][NFC] ML InlineAdvisor: Factored CHECKs in common test The CHECKs are going to be shared with the development mode test --- llvm/test/Transforms/Inline/ML/Inputs/test-module.ll | 6 +++++- llvm/test/Transforms/Inline/ML/ml-test-release-mode.ll | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/llvm/test/Transforms/Inline/ML/Inputs/test-module.ll b/llvm/test/Transforms/Inline/ML/Inputs/test-module.ll index b8279e5db6a02..d01f4bb301a86 100644 --- a/llvm/test/Transforms/Inline/ML/Inputs/test-module.ll +++ b/llvm/test/Transforms/Inline/ML/Inputs/test-module.ll @@ -61,4 +61,8 @@ define i32 @switcher(i32) { ;

*internal, + std::size_t internalLength, void ** /*scratchArea*/, + std::size_t /*scratchBytes*/, const char *sourceFile, int sourceLine) { + Terminator oom{sourceFile, sourceLine}; + return &New>{oom}( + internal, internalLength, sourceFile, sourceLine) + .release() + ->ioStatementState(); +} + +Cookie IONAME(BeginInternalListOutput)(char *internal, + std::size_t internalLength, void **scratchArea, std::size_t scratchBytes, + const char *sourceFile, int sourceLine) { + return BeginInternalListIO(internal, internalLength, + scratchArea, scratchBytes, sourceFile, sourceLine); +} + +Cookie IONAME(BeginInternalListInput)(const char *internal, + std::size_t internalLength, void **scratchArea, std::size_t scratchBytes, + const char *sourceFile, int sourceLine) { + return BeginInternalListIO(internal, internalLength, + scratchArea, scratchBytes, sourceFile, sourceLine); +} + template Cookie BeginInternalFormattedIO( std::conditional_t *internal, @@ -90,7 +116,6 @@ Cookie IONAME(BeginInternalFormattedOutput)(char *internal, std::size_t internalLength, const char *format, std::size_t formatLength, void **scratchArea, std::size_t scratchBytes, const char *sourceFile, int sourceLine) { - Terminator oom{sourceFile, sourceLine}; return BeginInternalFormattedIO(internal, internalLength, format, formatLength, scratchArea, scratchBytes, sourceFile, sourceLine); } @@ -99,7 +124,6 @@ Cookie IONAME(BeginInternalFormattedInput)(const char *internal, std::size_t internalLength, const char *format, std::size_t formatLength, void **scratchArea, std::size_t scratchBytes, const char *sourceFile, int sourceLine) { - Terminator oom{sourceFile, sourceLine}; return BeginInternalFormattedIO(internal, internalLength, format, formatLength, scratchArea, scratchBytes, sourceFile, sourceLine); } From 66b66988e613a2349d06600e12601ecbe8032256 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Fri, 17 Jul 2020 22:28:36 +0300 Subject: [PATCH 670/771] [NFC][InstCombine] Add some tests with sdiv-by-negative-power-of-two --- ...f-non-negative-by-negative-power-of-two.ll | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll diff --git a/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll b/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll new file mode 100644 index 0000000000000..c10a98a41acba --- /dev/null +++ b/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll @@ -0,0 +1,47 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt %s -instcombine -S | FileCheck %s + +; Fold +; x s/ (-1 << y) +; to +; -(x >> y) +; iff x is known non-negative. + +declare void @llvm.assume(i1) + +define i8 @t0(i8 %x, i8 %y) { +; CHECK-LABEL: @t0( +; CHECK-NEXT: [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]]) +; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[X]], -32 +; CHECK-NEXT: ret i8 [[DIV]] +; + %x_is_nonnegative = icmp sge i8 %x, 0 + call void @llvm.assume(i1 %x_is_nonnegative) + %div = sdiv i8 %x, -32 + ret i8 %div +} +define i8 @n1(i8 %x, i8 %y) { +; CHECK-LABEL: @n1( +; CHECK-NEXT: [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -2 +; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]]) +; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[X]], -32 +; CHECK-NEXT: ret i8 [[DIV]] +; + %x_is_nonnegative = icmp sge i8 %x, -1 ; could be negative + call void @llvm.assume(i1 %x_is_nonnegative) + %div = sdiv i8 %x, -32 + ret i8 %div +} +define i8 @n2(i8 %x, i8 %y) { +; CHECK-LABEL: @n2( +; CHECK-NEXT: [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -1 +; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]]) +; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[X]], -31 +; CHECK-NEXT: ret i8 [[DIV]] +; + %x_is_nonnegative = icmp sge i8 %x, 0 + call void @llvm.assume(i1 %x_is_nonnegative) + %div = sdiv i8 %x, -31 ; not a negative power of two + ret i8 %div +} From 0fdcca07ad2c0bdc2cdd40ba638109926f4f513b Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Fri, 17 Jul 2020 22:35:21 +0300 Subject: [PATCH 671/771] [InstCombine] Fold X sdiv (-1 << C) -> -(X u>> Y) iff X is non-negative This is the one i'm seeing as missed optimization, although there are likely other possibilities, as usual. There are 4 variants of a general sdiv->udiv fold: https://rise4fun.com/Alive/VS6 Name: v0 Pre: C0 >= 0 && C1 >= 0 %r = sdiv i8 C0, C1 => %r = udiv i8 C0, C1 Name: v1 Pre: C0 <= 0 && C1 >= 0 %r = sdiv i8 C0, C1 => %t0 = udiv i8 -C0, C1 %r = sub i8 0, %t0 Name: v2 Pre: C0 >= 0 && C1 <= 0 %r = sdiv i8 C0, C1 => %t0 = udiv i8 C0, -C1 %r = sub i8 0, %t0 Name: v3 Pre: C0 <= 0 && C1 <= 0 %r = sdiv i8 C0, C1 => %r = udiv i8 -C0, -C1 If we really don't like sdiv (more than udiv that is), and are okay with increasing instruction count (2 new negations), and we ensure that we don't undo the fold, then we could just implement these.. --- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 7 +++++++ .../sdiv-of-non-negative-by-negative-power-of-two.ll | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index c6233a68847dd..f039989c004ce 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1182,6 +1182,13 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) { return BO; } + if (match(Op1, m_NegatedPower2())) { + // X sdiv (-(1 << C)) -> -(X sdiv (1 << C)) -> + // -> -(X udiv (1 << C)) -> -(X u>> C) + return BinaryOperator::CreateNeg(Builder.Insert(foldUDivPow2Cst( + Op0, ConstantExpr::getNeg(cast(Op1)), I, *this))); + } + if (isKnownToBeAPowerOfTwo(Op1, /*OrZero*/ true, 0, &I)) { // X sdiv (1 << Y) -> X udiv (1 << Y) ( -> X u>> Y) // Safe because the only negative value (1 << Y) can take on is diff --git a/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll b/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll index c10a98a41acba..f9dd32bfc612d 100644 --- a/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll +++ b/llvm/test/Transforms/InstCombine/sdiv-of-non-negative-by-negative-power-of-two.ll @@ -13,7 +13,8 @@ define i8 @t0(i8 %x, i8 %y) { ; CHECK-LABEL: @t0( ; CHECK-NEXT: [[X_IS_NONNEGATIVE:%.*]] = icmp sgt i8 [[X:%.*]], -1 ; CHECK-NEXT: call void @llvm.assume(i1 [[X_IS_NONNEGATIVE]]) -; CHECK-NEXT: [[DIV:%.*]] = sdiv i8 [[X]], -32 +; CHECK-NEXT: [[TMP1:%.*]] = lshr i8 [[X]], 5 +; CHECK-NEXT: [[DIV:%.*]] = sub nsw i8 0, [[TMP1]] ; CHECK-NEXT: ret i8 [[DIV]] ; %x_is_nonnegative = icmp sge i8 %x, 0 From d8e0baf29daa58233c349d94ca4617065efc4c95 Mon Sep 17 00:00:00 2001 From: Xinan Jiang Date: Fri, 17 Jul 2020 20:57:08 +0100 Subject: [PATCH 672/771] [InstCombine] Fix typo in comment. Reviewers: fhahn Reviewed By: fhahn Differential Revision: https://reviews.llvm.org/D83951 --- .../shift-amount-reassociation-with-truncation-shl.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll index 7ae9b76fa5fee..0808b9a3763ef 100644 --- a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll +++ b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll @@ -194,7 +194,7 @@ define i16 @n11(i32 %x, i16 %y) { ret i16 %t5 } -; Bit width mismatch of shit amount +; Bit width mismatch of shift amount @Y32 = global i32 42 @Y16 = global i16 42 From 502f0cc0e3889229e923e187f38dda91324ae139 Mon Sep 17 00:00:00 2001 From: Mitch Phillips <31459023+hctim@users.noreply.github.com> Date: Fri, 17 Jul 2020 12:59:09 -0700 Subject: [PATCH 673/771] [GWP-ASan] Split the unwinder into segv/non-segv. Summary: Splits the unwinder into a non-segv (for allocation/deallocation traces) and a segv unwinder. This ensures that implementations can select an accurate, slower unwinder in the segv handler (if they choose to use the GWP-ASan provided one). This is important as fast frame-pointer unwinders (like the sanitizer unwinder) don't like unwinding through signal handlers. Reviewers: morehouse, cryptoad Reviewed By: morehouse, cryptoad Subscribers: cryptoad, mgorny, eugenis, pcc, #sanitizers Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D83994 --- .../optional/backtrace_linux_libc.cpp | 12 ++++++ .../optional/backtrace_sanitizer_common.cpp | 37 +++++++++++++++---- .../lib/gwp_asan/optional/segv_handler.h | 15 ++++++-- .../gwp_asan/optional/segv_handler_posix.cpp | 17 +++++---- compiler-rt/lib/gwp_asan/tests/CMakeLists.txt | 3 +- compiler-rt/lib/gwp_asan/tests/harness.h | 3 +- compiler-rt/lib/scudo/scudo_allocator.cpp | 4 +- compiler-rt/lib/scudo/standalone/combined.h | 2 +- compiler-rt/test/gwp_asan/backtrace.c | 29 +++++++++++++++ 9 files changed, 99 insertions(+), 23 deletions(-) create mode 100644 compiler-rt/test/gwp_asan/backtrace.c diff --git a/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp b/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp index bb0aad224a14c..92eb293dab499 100644 --- a/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp +++ b/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp @@ -23,6 +23,14 @@ size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) { return backtrace(reinterpret_cast(TraceBuffer), Size); } +// We don't need any custom handling for the Segv backtrace - the libc unwinder +// has no problems with unwinding through a signal handler. Force inlining here +// to avoid the additional frame. +GWP_ASAN_ALWAYS_INLINE size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size, + void * /*Context*/) { + return Backtrace(TraceBuffer, Size); +} + static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength, gwp_asan::crash_handler::Printf_t Printf) { if (TraceLength == 0) { @@ -53,4 +61,8 @@ crash_handler::PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; } } // namespace options + +namespace crash_handler { +SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; } +} // namespace crash_handler } // namespace gwp_asan diff --git a/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp b/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp index 3ac4b52bfc271..a8083e4e64cb3 100644 --- a/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp +++ b/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp @@ -22,28 +22,45 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { - if (!StackTrace::WillUseFastUnwind(request_fast)) { - return Unwind(max_depth, pc, bp, context, 0, 0, request_fast); - } - Unwind(max_depth, pc, 0, context, 0, 0, false); + if (!StackTrace::WillUseFastUnwind(request_fast)) + return Unwind(max_depth, pc, 0, context, 0, 0, false); + + uptr top = 0; + uptr bottom = 0; + GetThreadStackTopAndBottom(/*at_initialization*/ false, &top, &bottom); + + return Unwind(max_depth, pc, bp, context, top, bottom, request_fast); } namespace { -size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) { +size_t BacktraceCommon(uintptr_t *TraceBuffer, size_t Size, void *Context) { + // Use the slow sanitizer unwinder in the segv handler. Fast frame pointer + // unwinders can end up dropping frames because the kernel sigreturn() frame's + // return address is the return address at time of fault. This has the result + // of never actually capturing the PC where the signal was raised. + bool UseFastUnwind = (Context == nullptr); + __sanitizer::BufferedStackTrace Trace; Trace.Reset(); if (Size > __sanitizer::kStackTraceMax) Size = __sanitizer::kStackTraceMax; Trace.Unwind((__sanitizer::uptr)__builtin_return_address(0), - (__sanitizer::uptr)__builtin_frame_address(0), - /* ucontext */ nullptr, - /* fast unwind */ true, Size - 1); + (__sanitizer::uptr)__builtin_frame_address(0), Context, + UseFastUnwind, Size - 1); memcpy(TraceBuffer, Trace.trace, Trace.size * sizeof(uintptr_t)); return Trace.size; } +size_t Backtrace(uintptr_t *TraceBuffer, size_t Size) { + return BacktraceCommon(TraceBuffer, Size, nullptr); +} + +size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size, void *Context) { + return BacktraceCommon(TraceBuffer, Size, Context); +} + static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength, gwp_asan::crash_handler::Printf_t Printf) { __sanitizer::StackTrace StackTrace; @@ -77,4 +94,8 @@ crash_handler::PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; } } // namespace options + +namespace crash_handler { +SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; } +} // namespace crash_handler } // namespace gwp_asan diff --git a/compiler-rt/lib/gwp_asan/optional/segv_handler.h b/compiler-rt/lib/gwp_asan/optional/segv_handler.h index 10af15055e2a8..0fed4f2e012e9 100644 --- a/compiler-rt/lib/gwp_asan/optional/segv_handler.h +++ b/compiler-rt/lib/gwp_asan/optional/segv_handler.h @@ -59,6 +59,15 @@ typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength, // without any symbolization. PrintBacktrace_t getBasicPrintBacktraceFunction(); +// Returns a function pointer to a backtrace function that's suitable for +// unwinding through a signal handler. This is important primarily for frame- +// pointer based unwinders, DWARF or other unwinders can simply provide the +// normal backtrace function as the implementation here. On POSIX, SignalContext +// should be the `ucontext_t` from the signal handler. +typedef size_t (*SegvBacktrace_t)(uintptr_t *TraceBuffer, size_t Size, + void *SignalContext); +SegvBacktrace_t getSegvBacktraceFunction(); + // Install the SIGSEGV crash handler for printing use-after-free and heap- // buffer-{under|over}flow exceptions if the user asked for it. This is platform // specific as even though POSIX and Windows both support registering handlers @@ -67,14 +76,14 @@ PrintBacktrace_t getBasicPrintBacktraceFunction(); // before this function. void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf, PrintBacktrace_t PrintBacktrace, - options::Backtrace_t Backtrace); + SegvBacktrace_t SegvBacktrace); void uninstallSignalHandlers(); void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State, const gwp_asan::AllocationMetadata *Metadata, - options::Backtrace_t Backtrace, Printf_t Printf, - PrintBacktrace_t PrintBacktrace); + SegvBacktrace_t SegvBacktrace, Printf_t Printf, + PrintBacktrace_t PrintBacktrace, void *Context); } // namespace crash_handler } // namespace gwp_asan diff --git a/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp b/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp index 22589b893604f..1bd7a606c2136 100644 --- a/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp +++ b/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp @@ -23,14 +23,14 @@ using gwp_asan::Error; using gwp_asan::GuardedPoolAllocator; using gwp_asan::crash_handler::PrintBacktrace_t; using gwp_asan::crash_handler::Printf_t; -using gwp_asan::options::Backtrace_t; +using gwp_asan::crash_handler::SegvBacktrace_t; struct sigaction PreviousHandler; bool SignalHandlerInstalled; gwp_asan::GuardedPoolAllocator *GPAForSignalHandler; Printf_t PrintfForSignalHandler; PrintBacktrace_t PrintBacktraceForSignalHandler; -Backtrace_t BacktraceForSignalHandler; +SegvBacktrace_t BacktraceForSignalHandler; static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) { if (GPAForSignalHandler) { @@ -40,7 +40,7 @@ static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) { reinterpret_cast(info->si_addr), GPAForSignalHandler->getAllocatorState(), GPAForSignalHandler->getMetadataRegion(), BacktraceForSignalHandler, - PrintfForSignalHandler, PrintBacktraceForSignalHandler); + PrintfForSignalHandler, PrintBacktraceForSignalHandler, ucontext); } // Process any previous handlers. @@ -138,11 +138,11 @@ PrintBacktrace_t getBasicPrintBacktraceFunction() { void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf, PrintBacktrace_t PrintBacktrace, - options::Backtrace_t Backtrace) { + SegvBacktrace_t SegvBacktrace) { GPAForSignalHandler = GPA; PrintfForSignalHandler = Printf; PrintBacktraceForSignalHandler = PrintBacktrace; - BacktraceForSignalHandler = Backtrace; + BacktraceForSignalHandler = SegvBacktrace; struct sigaction Action; Action.sa_sigaction = sigSegvHandler; @@ -160,8 +160,8 @@ void uninstallSignalHandlers() { void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State, const gwp_asan::AllocationMetadata *Metadata, - options::Backtrace_t Backtrace, Printf_t Printf, - PrintBacktrace_t PrintBacktrace) { + SegvBacktrace_t SegvBacktrace, Printf_t Printf, + PrintBacktrace_t PrintBacktrace, void *Context) { assert(State && "dumpReport missing Allocator State."); assert(Metadata && "dumpReport missing Metadata."); assert(Printf && "dumpReport missing Printf."); @@ -194,7 +194,8 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State, // Print the fault backtrace. static constexpr unsigned kMaximumStackFramesForCrashTrace = 512; uintptr_t Trace[kMaximumStackFramesForCrashTrace]; - size_t TraceLength = Backtrace(Trace, kMaximumStackFramesForCrashTrace); + size_t TraceLength = + SegvBacktrace(Trace, kMaximumStackFramesForCrashTrace, Context); PrintBacktrace(Trace, TraceLength, Printf); diff --git a/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt b/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt index feac23df9fe5d..f88d90c19d5b9 100644 --- a/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt @@ -5,7 +5,8 @@ set(GWP_ASAN_UNITTEST_CFLAGS ${COMPILER_RT_GTEST_CFLAGS} -I${COMPILER_RT_SOURCE_DIR}/lib/ -O2 - -g) + -g + -fno-omit-frame-pointer) file(GLOB GWP_ASAN_HEADERS ../*.h) set(GWP_ASAN_UNITTESTS diff --git a/compiler-rt/lib/gwp_asan/tests/harness.h b/compiler-rt/lib/gwp_asan/tests/harness.h index e47254e13c467..d303b2cfa6470 100644 --- a/compiler-rt/lib/gwp_asan/tests/harness.h +++ b/compiler-rt/lib/gwp_asan/tests/harness.h @@ -86,7 +86,8 @@ class BacktraceGuardedPoolAllocator : public ::testing::Test { gwp_asan::crash_handler::installSignalHandlers( &GPA, gwp_asan::test::getPrintfFunction(), - gwp_asan::options::getPrintBacktraceFunction(), Opts.Backtrace); + gwp_asan::options::getPrintBacktraceFunction(), + gwp_asan::crash_handler::getSegvBacktraceFunction()); } void TearDown() override { diff --git a/compiler-rt/lib/scudo/scudo_allocator.cpp b/compiler-rt/lib/scudo/scudo_allocator.cpp index d9023c2f7ab64..343f85a4ef88b 100644 --- a/compiler-rt/lib/scudo/scudo_allocator.cpp +++ b/compiler-rt/lib/scudo/scudo_allocator.cpp @@ -29,6 +29,7 @@ # include "gwp_asan/guarded_pool_allocator.h" # include "gwp_asan/optional/backtrace.h" # include "gwp_asan/optional/options_parser.h" +#include "gwp_asan/optional/segv_handler.h" #endif // GWP_ASAN_HOOKS #include @@ -679,7 +680,8 @@ void initScudo() { if (Opts.InstallSignalHandlers) gwp_asan::crash_handler::installSignalHandlers( &GuardedAlloc, __sanitizer::Printf, - gwp_asan::options::getPrintBacktraceFunction(), Opts.Backtrace); + gwp_asan::options::getPrintBacktraceFunction(), + gwp_asan::crash_handler::getSegvBacktraceFunction()); #endif // GWP_ASAN_HOOKS } diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 3bb41eca88f72..ae085befc4f15 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -192,7 +192,7 @@ class Allocator { if (Opt.InstallSignalHandlers) gwp_asan::crash_handler::installSignalHandlers( &GuardedAlloc, Printf, gwp_asan::options::getPrintBacktraceFunction(), - Opt.Backtrace); + gwp_asan::crash_handler::getSegvBacktraceFunction()); #endif // GWP_ASAN_HOOKS } diff --git a/compiler-rt/test/gwp_asan/backtrace.c b/compiler-rt/test/gwp_asan/backtrace.c new file mode 100644 index 0000000000000..0ba32f85cbf97 --- /dev/null +++ b/compiler-rt/test/gwp_asan/backtrace.c @@ -0,0 +1,29 @@ +// REQUIRES: gwp_asan +// RUN: %clang_gwp_asan %s -g -o %t +// RUN: %expect_crash %t 2>&1 | FileCheck %s + +#include + +__attribute__((noinline)) void *allocate_mem() { return malloc(1); } + +__attribute__((noinline)) void free_mem(void *ptr) { free(ptr); } + +__attribute__((noinline)) void touch_mem(void *ptr) { + volatile char sink = *((volatile char *)ptr); +} + +// CHECK: Use After Free +// CHECK: touch_mem +// CHECK: was deallocated +// CHECK: free_mem +// CHECK: was allocated +// CHECK: allocate_mem + +int main() { + for (unsigned i = 0; i < 0x10000; ++i) { + void *ptr = allocate_mem(); + free_mem(ptr); + touch_mem(ptr); + } + return 0; +} From ec6ada62643cf7cded8160e04cce163323112ade Mon Sep 17 00:00:00 2001 From: Xiangling Liao Date: Thu, 16 Jul 2020 14:29:13 -0400 Subject: [PATCH 674/771] [AIX] report_fatal_error on `-fregister_global_dtors_with_atexit` for static init On AIX, the semantic of global_dtors contains __sterm functions associated with C++ cleanup actions and user-declared __attribute__((destructor)) functions. We should never merely register __sterm with atexit(), so currently -fregister_global_dtors_with_atexit does not work well on AIX: It would cause finalization actions to not occur when unloading shared libraries. We need to figure out a way to handle that when we start supporting user-declared __attribute__((destructor)) functions. Currently we report_fatal_error on this option temporarily. Differential Revision: https://reviews.llvm.org/D83974 --- clang/lib/CodeGen/CodeGenModule.cpp | 3 +++ ...aix-sinit-register-global-dtors-with-atexit.cpp | 14 ++++++++++++++ clang/test/Driver/cxa-atexit.cpp | 14 ++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 clang/test/CodeGenCXX/aix-sinit-register-global-dtors-with-atexit.cpp diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 4ae8ce7e5ccf1..4c792520b5f37 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1209,6 +1209,9 @@ void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority, /// when the module is unloaded. void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority) { if (CodeGenOpts.RegisterGlobalDtorsWithAtExit) { + if (getCXXABI().useSinitAndSterm()) + llvm::report_fatal_error( + "register global dtors with atexit() is not supported yet"); DtorsUsingAtExit[Priority].push_back(Dtor); return; } diff --git a/clang/test/CodeGenCXX/aix-sinit-register-global-dtors-with-atexit.cpp b/clang/test/CodeGenCXX/aix-sinit-register-global-dtors-with-atexit.cpp new file mode 100644 index 0000000000000..4cec83d461ade --- /dev/null +++ b/clang/test/CodeGenCXX/aix-sinit-register-global-dtors-with-atexit.cpp @@ -0,0 +1,14 @@ +// RUN: not %clang_cc1 -triple powerpc-ibm-aix-xcoff -S -emit-llvm -x c++ \ +// RUN: -fregister-global-dtors-with-atexit < %s 2>&1 | \ +// RUN: FileCheck %s + +// RUN: not %clang_cc1 -triple powerpc64-ibm-aix-xcoff -S -emit-llvm -x c++ \ +// RUN: -fregister-global-dtors-with-atexit < %s 2>&1 | \ +// RUN: FileCheck %s + +struct T { + T(); + ~T(); +} t; + +// CHECK: error in backend: register global dtors with atexit() is not supported yet diff --git a/clang/test/Driver/cxa-atexit.cpp b/clang/test/Driver/cxa-atexit.cpp index e81af6cd5963d..537a11a35f51b 100644 --- a/clang/test/Driver/cxa-atexit.cpp +++ b/clang/test/Driver/cxa-atexit.cpp @@ -36,6 +36,7 @@ // RUN: FileCheck --check-prefix=WITHATEXIT %s // RUN: %clang -target x86_64-apple-darwin -c -mkernel -### %s 2>&1 | \ // RUN: FileCheck --check-prefix=WITHOUTATEXIT %s + // RUN: %clang -target x86_64-pc-linux-gnu -fregister-global-dtors-with-atexit -fno-register-global-dtors-with-atexit -c -### %s 2>&1 | \ // RUN: FileCheck --check-prefix=WITHOUTATEXIT %s // RUN: %clang -target x86_64-pc-linux-gnu -fno-register-global-dtors-with-atexit -fregister-global-dtors-with-atexit -c -### %s 2>&1 | \ @@ -43,5 +44,18 @@ // RUN: %clang -target x86_64-pc-linux-gnu -c -### %s 2>&1 | \ // RUN: FileCheck --check-prefix=WITHOUTATEXIT %s +// RUN: %clang -target powerpc-ibm-aix-xcoff -fregister-global-dtors-with-atexit -fno-register-global-dtors-with-atexit -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=WITHOUTATEXIT %s +// RUN: %clang -target powerpc-ibm-aix-xcoff -fno-register-global-dtors-with-atexit -fregister-global-dtors-with-atexit -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=WITHATEXIT %s +// RUN: %clang -target powerpc-ibm-aix-xcoff -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=WITHOUTATEXIT %s +// RUN: %clang -target powerpc64-ibm-aix-xcoff -fregister-global-dtors-with-atexit -fno-register-global-dtors-with-atexit -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=WITHOUTATEXIT %s +// RUN: %clang -target powerpc64-ibm-aix-xcoff -fno-register-global-dtors-with-atexit -fregister-global-dtors-with-atexit -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=WITHATEXIT %s +// RUN: %clang -target powerpc64-ibm-aix-xcoff -c -### %s 2>&1 | \ +// RUN: FileCheck --check-prefix=WITHOUTATEXIT %s + // WITHATEXIT: -fregister-global-dtors-with-atexit // WITHOUTATEXIT-NOT: -fregister-global-dtors-with-atexit From 029946b112684c27b27f7c2d7554f22b33ae1e0b Mon Sep 17 00:00:00 2001 From: Wenlei He Date: Mon, 13 Jul 2020 22:12:28 -0700 Subject: [PATCH 675/771] [InlineAdvisor] New inliner advisor to replay inlining from optimization remarks Summary: This change added a new inline advisor that takes optimization remarks for previous inlining as input, and provide the decision as advice so current inlining can replay inline decision of a different compilation. Dwarf inline stack with line and discriminator is used as anchor for call sites. The change can be useful for Inliner tuning. A switch -sample-profile-inline-replay= is added to hook up the new inliner advisor with SampleProfileLoader's inline decision for replay. The new inline advisor can also be used by regular CGSCC inliner later if needed. Reviewers: davidxl, mtrofin, wmi, hoy Subscribers: aprantl, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D83743 --- llvm/include/llvm/Analysis/InlineAdvisor.h | 3 + .../llvm/Analysis/ReplayInlineAdvisor.h | 37 ++++++ llvm/lib/Analysis/CMakeLists.txt | 1 + llvm/lib/Analysis/InlineAdvisor.cpp | 25 ++++ llvm/lib/Analysis/ReplayInlineAdvisor.cpp | 61 +++++++++ llvm/lib/Transforms/IPO/SampleProfile.cpp | 37 +++++- .../SampleProfile/Inputs/inline-replay.txt | 2 + .../Transforms/SampleProfile/inline-replay.ll | 122 ++++++++++++++++++ 8 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 llvm/include/llvm/Analysis/ReplayInlineAdvisor.h create mode 100644 llvm/lib/Analysis/ReplayInlineAdvisor.cpp create mode 100644 llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt create mode 100644 llvm/test/Transforms/SampleProfile/inline-replay.ll diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h index 3480d93385a8e..a0ff09679dfed 100644 --- a/llvm/include/llvm/Analysis/InlineAdvisor.h +++ b/llvm/include/llvm/Analysis/InlineAdvisor.h @@ -226,6 +226,9 @@ void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, bool ForProfileContext = false, const char *PassName = nullptr); +/// get call site location as string +StringRef getCallSiteLocation(DebugLoc DLoc); + /// Add location info to ORE message. void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc); diff --git a/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h b/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h new file mode 100644 index 0000000000000..e312d59a9f87b --- /dev/null +++ b/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h @@ -0,0 +1,37 @@ +//===- ReplayInlineAdvisor.h - Replay Inline Advisor interface -*- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +#ifndef LLVM_REPLAYINLINEADVISOR_H_ +#define LLVM_REPLAYINLINEADVISOR_H_ + +#include "llvm/ADT/StringSet.h" +#include "llvm/Analysis/InlineAdvisor.h" +#include "llvm/IR/LLVMContext.h" + +namespace llvm { +class BasicBlock; +class CallBase; +class Function; +class Module; +class OptimizationRemarkEmitter; + +/// Replay inline advisor that uses optimization remarks from inlining of +/// previous build to guide current inlining. This is useful for inliner tuning. +class ReplayInlineAdvisor : public InlineAdvisor { +public: + ReplayInlineAdvisor(FunctionAnalysisManager &FAM, LLVMContext &Context, + StringRef RemarksFile); + std::unique_ptr getAdvice(CallBase &CB) override; + bool areReplayRemarksLoaded() const { return HasReplayRemarks; } + +private: + StringSet<> InlineSitesFromRemarks; + bool HasReplayRemarks = false; +}; +} // namespace llvm +#endif // LLVM_REPLAYINLINEADVISOR_H_ \ No newline at end of file diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 703623396d96a..8f10bac588e52 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -117,6 +117,7 @@ add_llvm_component_library(LLVMAnalysis RegionInfo.cpp RegionPass.cpp RegionPrinter.cpp + ReplayInlineAdvisor.cpp ScalarEvolution.cpp ScalarEvolutionAliasAnalysis.cpp ScalarEvolutionDivision.cpp diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp index e18f681278d3a..fedc5282ee646 100644 --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -365,6 +365,31 @@ llvm::shouldInline(CallBase &CB, return IC; } +StringRef llvm::getCallSiteLocation(DebugLoc DLoc) { + std::ostringstream CallSiteLoc; + bool First = true; + for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) { + if (!First) + CallSiteLoc << " @ "; + // Note that negative line offset is actually possible, but we use + // unsigned int to match line offset representation in remarks so + // it's directly consumable by relay advisor. + uint32_t Offset = + DIL->getLine() - DIL->getScope()->getSubprogram()->getLine(); + uint32_t Discriminator = DIL->getBaseDiscriminator(); + StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName(); + if (Name.empty()) + Name = DIL->getScope()->getSubprogram()->getName(); + CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset); + if (Discriminator) { + CallSiteLoc << "." << llvm::utostr(Discriminator); + } + First = false; + } + + return CallSiteLoc.str(); +} + void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) { if (!DLoc.get()) return; diff --git a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp new file mode 100644 index 0000000000000..c12b58021a606 --- /dev/null +++ b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp @@ -0,0 +1,61 @@ +//===- ReplayInlineAdvisor.cpp - Replay InlineAdvisor ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements ReplayInlineAdvisor that replays inline decision based +// on previous inline remarks from optimization remark log. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/InlineAdvisor.h" +#include "llvm/Analysis/ReplayInlineAdvisor.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/LineIterator.h" + +using namespace llvm; + +#define DEBUG_TYPE "inline-replay" + +ReplayInlineAdvisor::ReplayInlineAdvisor(FunctionAnalysisManager &FAM, + LLVMContext &Context, + StringRef RemarksFile) + : InlineAdvisor(FAM), HasReplayRemarks(false) { + auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(RemarksFile); + std::error_code EC = BufferOrErr.getError(); + if (EC) { + Context.emitError("Could not open remarks file: " + EC.message()); + return; + } + + // Example for inline remarks to parse: + // _Z3subii inlined into main [details] at callsite sum:1 @ main:3.1 + // We use the callsite string after `at callsite` to replay inlining. + line_iterator LineIt(*BufferOrErr.get(), /*SkipBlanks=*/true); + for (; !LineIt.is_at_eof(); ++LineIt) { + StringRef Line = *LineIt; + auto Pair = Line.split(" at callsite "); + if (Pair.second.empty()) + continue; + InlineSitesFromRemarks.insert(Pair.second); + } + HasReplayRemarks = true; +} + +std::unique_ptr ReplayInlineAdvisor::getAdvice(CallBase &CB) { + assert(HasReplayRemarks); + + Function &Caller = *CB.getCaller(); + auto &ORE = FAM.getResult(Caller); + + if (InlineSitesFromRemarks.empty()) + return std::make_unique(this, CB, ORE, false); + + StringRef CallSiteLoc = getCallSiteLocation(CB.getDebugLoc()); + bool InlineRecommended = InlineSitesFromRemarks.count(CallSiteLoc) > 0; + return std::make_unique(this, CB, ORE, InlineRecommended); +} diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index b6871e260532d..7b5fc030cf88c 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -43,6 +43,7 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ProfileSummaryInfo.h" +#include "llvm/Analysis/ReplayInlineAdvisor.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/BasicBlock.h" @@ -170,6 +171,13 @@ static cl::opt SampleColdCallSiteThreshold( "sample-profile-cold-inline-threshold", cl::Hidden, cl::init(45), cl::desc("Threshold for inlining cold callsites")); +static cl::opt ProfileInlineReplayFile( + "sample-profile-inline-replay", cl::init(""), cl::value_desc("filename"), + cl::desc( + "Optimization remarks file containing inline remarks to be replayed " + "by inlining from sample profile loader."), + cl::Hidden); + namespace { using BlockWeightMap = DenseMap; @@ -319,7 +327,7 @@ class SampleProfileLoader { RemappingFilename(std::string(RemapName)), IsThinLTOPreLink(IsThinLTOPreLink) {} - bool doInitialization(Module &M); + bool doInitialization(Module &M, FunctionAnalysisManager *FAM = nullptr); bool runOnModule(Module &M, ModuleAnalysisManager *AM, ProfileSummaryInfo *_PSI, CallGraph *CG); @@ -473,6 +481,9 @@ class SampleProfileLoader { // overriden by -profile-sample-accurate or profile-sample-accurate // attribute. bool ProfAccForSymsInList; + + // External inline advisor used to replay inline decision from remarks. + std::unique_ptr ExternalInlineAdvisor; }; class SampleProfileLoaderLegacyPass : public ModulePass { @@ -898,6 +909,16 @@ SampleProfileLoader::findFunctionSamples(const Instruction &Inst) const { } bool SampleProfileLoader::inlineCallInstruction(CallBase &CB) { + if (ExternalInlineAdvisor) { + auto Advice = ExternalInlineAdvisor->getAdvice(CB); + if (!Advice->isInliningRecommended()) { + Advice->recordUnattemptedInlining(); + return false; + } + // Dummy record, we don't use it for replay. + Advice->recordInlining(); + } + Function *CalledFunction = CB.getCalledFunction(); assert(CalledFunction); DebugLoc DLoc = CB.getDebugLoc(); @@ -1005,7 +1026,7 @@ bool SampleProfileLoader::inlineHotFunctions( } } } - if (Hot) { + if (Hot || ExternalInlineAdvisor) { CIS.insert(CIS.begin(), AllCandidates.begin(), AllCandidates.end()); emitOptimizationRemarksForInlineCandidates(AllCandidates, F, true); } else { @@ -1818,7 +1839,8 @@ SampleProfileLoader::buildFunctionOrder(Module &M, CallGraph *CG) { return FunctionOrderList; } -bool SampleProfileLoader::doInitialization(Module &M) { +bool SampleProfileLoader::doInitialization(Module &M, + FunctionAnalysisManager *FAM) { auto &Ctx = M.getContext(); std::unique_ptr RemapReader; @@ -1843,6 +1865,13 @@ bool SampleProfileLoader::doInitialization(Module &M) { NamesInProfile.insert(NameTable->begin(), NameTable->end()); } + if (FAM && !ProfileInlineReplayFile.empty()) { + ExternalInlineAdvisor = std::make_unique( + *FAM, Ctx, ProfileInlineReplayFile); + if (!ExternalInlineAdvisor->areReplayRemarksLoaded()) + ExternalInlineAdvisor.reset(); + } + return true; } @@ -1995,7 +2024,7 @@ PreservedAnalyses SampleProfileLoaderPass::run(Module &M, : ProfileRemappingFileName, IsThinLTOPreLink, GetAssumptionCache, GetTTI, GetTLI); - if (!SampleLoader.doInitialization(M)) + if (!SampleLoader.doInitialization(M, &FAM)) return PreservedAnalyses::all(); ProfileSummaryInfo *PSI = &AM.getResult(M); diff --git a/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt b/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt new file mode 100644 index 0000000000000..6842845d56554 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt @@ -0,0 +1,2 @@ +remark: calls.cc:10:0: _Z3sumii inlined into main to match profiling context with (cost=45, threshold=337) at callsite main:3.1 +remark: calls.cc:4:0: _Z3subii inlined into main to match profiling context with (cost=-5, threshold=337) at callsite _Z3sumii:1 @ main:3.1 diff --git a/llvm/test/Transforms/SampleProfile/inline-replay.ll b/llvm/test/Transforms/SampleProfile/inline-replay.ll new file mode 100644 index 0000000000000..ecf6f51850f26 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/inline-replay.ll @@ -0,0 +1,122 @@ +;; Note that this needs new pass manager for now. Passing `-sample-profile-inline-replay` to legacy pass manager is a no-op. + +;; Check baseline inline decisions +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline-topdown.prof -sample-profile-merge-inlinee -sample-profile-top-down-load -pass-remarks=inline -S 2>&1 | FileCheck -check-prefix=DEFAULT %s + +;; Check replay inline decisions +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline-topdown.prof -sample-profile-inline-replay=%S/Inputs/inline-replay.txt -sample-profile-merge-inlinee -sample-profile-top-down-load -pass-remarks=inline -S 2>&1 | FileCheck -check-prefix=REPLAY %s + +@.str = private unnamed_addr constant [11 x i8] c"sum is %d\0A\00", align 1 + +define i32 @_Z3sumii(i32 %x, i32 %y) #0 !dbg !6 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %tmp = load i32, i32* %x.addr, align 4, !dbg !8 + %tmp1 = load i32, i32* %y.addr, align 4, !dbg !8 + %add = add nsw i32 %tmp, %tmp1, !dbg !8 + %tmp2 = load i32, i32* %x.addr, align 4, !dbg !8 + %tmp3 = load i32, i32* %y.addr, align 4, !dbg !8 + %call = call i32 @_Z3subii(i32 %tmp2, i32 %tmp3), !dbg !8 + ret i32 %add, !dbg !8 +} + +define i32 @_Z3subii(i32 %x, i32 %y) #0 !dbg !9 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %tmp = load i32, i32* %x.addr, align 4, !dbg !10 + %tmp1 = load i32, i32* %y.addr, align 4, !dbg !10 + %add = sub nsw i32 %tmp, %tmp1, !dbg !10 + ret i32 %add, !dbg !11 +} + +define i32 @main() #0 !dbg !12 { +entry: + %retval = alloca i32, align 4 + %s = alloca i32, align 4 + %i = alloca i32, align 4 + store i32 0, i32* %retval + store i32 0, i32* %i, align 4, !dbg !13 + br label %while.cond, !dbg !14 + +while.cond: ; preds = %if.end, %entry + %tmp = load i32, i32* %i, align 4, !dbg !15 + %inc = add nsw i32 %tmp, 1, !dbg !15 + store i32 %inc, i32* %i, align 4, !dbg !15 + %cmp = icmp slt i32 %tmp, 400000000, !dbg !15 + br i1 %cmp, label %while.body, label %while.end, !dbg !15 + +while.body: ; preds = %while.cond + %tmp1 = load i32, i32* %i, align 4, !dbg !17 + %cmp1 = icmp ne i32 %tmp1, 100, !dbg !17 + br i1 %cmp1, label %if.then, label %if.else, !dbg !17 + +if.then: ; preds = %while.body + %tmp2 = load i32, i32* %i, align 4, !dbg !19 + %tmp3 = load i32, i32* %s, align 4, !dbg !19 + %call = call i32 @_Z3sumii(i32 %tmp2, i32 %tmp3), !dbg !19 + store i32 %call, i32* %s, align 4, !dbg !19 + br label %if.end, !dbg !19 + +if.else: ; preds = %while.body + store i32 30, i32* %s, align 4, !dbg !21 + br label %if.end + +if.end: ; preds = %if.else, %if.then + br label %while.cond, !dbg !23 + +while.end: ; preds = %while.cond + %tmp4 = load i32, i32* %s, align 4, !dbg !25 + %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i32 %tmp4), !dbg !25 + ret i32 0, !dbg !26 +} + +declare i32 @printf(i8*, ...) + +attributes #0 = { "use-sample-profile" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.5 ", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!1 = !DIFile(filename: "calls.cc", directory: ".") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 1, !"Debug Info Version", i32 3} +!5 = !{!"clang version 3.5 "} +!6 = distinct !DISubprogram(name: "sum", linkageName: "_Z3sumii", scope: !1, file: !1, line: 3, type: !7, scopeLine: 3, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!7 = !DISubroutineType(types: !2) +!8 = !DILocation(line: 4, scope: !6) +!9 = distinct !DISubprogram(name: "sub", linkageName: "_Z3subii", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!10 = !DILocation(line: 20, scope: !9) +!11 = !DILocation(line: 21, scope: !9) +!12 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 7, type: !7, scopeLine: 7, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!13 = !DILocation(line: 8, scope: !12) +!14 = !DILocation(line: 9, scope: !12) +!15 = !DILocation(line: 9, scope: !16) +!16 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 2) +!17 = !DILocation(line: 10, scope: !18) +!18 = distinct !DILexicalBlock(scope: !12, file: !1, line: 10) +!19 = !DILocation(line: 10, scope: !20) +!20 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 2) +!21 = !DILocation(line: 10, scope: !22) +!22 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 4) +!23 = !DILocation(line: 10, scope: !24) +!24 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 6) +!25 = !DILocation(line: 11, scope: !12) +!26 = !DILocation(line: 12, scope: !12) + + +; DEFAULT: _Z3sumii inlined into main +; DEFAULT: _Z3subii inlined into _Z3sumii +; DEFAULT-NOT: _Z3subii inlined into main + +; REPLAY: _Z3sumii inlined into main +; REPLAY: _Z3subii inlined into main +; REPLA-NOT: _Z3subii inlined into _Z3sumii From c2d69d8d62f2aac941453177e2ae872f5f82feda Mon Sep 17 00:00:00 2001 From: Sjoerd Meijer Date: Fri, 17 Jul 2020 22:40:41 +0100 Subject: [PATCH 676/771] Remove clang matrix lowering test for now as it is still failing under the NPM. --- .../test/CodeGen/matrix-lowering-opt-levels.c | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 clang/test/CodeGen/matrix-lowering-opt-levels.c diff --git a/clang/test/CodeGen/matrix-lowering-opt-levels.c b/clang/test/CodeGen/matrix-lowering-opt-levels.c deleted file mode 100644 index 9edecbe46bc83..0000000000000 --- a/clang/test/CodeGen/matrix-lowering-opt-levels.c +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang -O1 -fenable-matrix -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang -O2 -fenable-matrix -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang -O3 -fenable-matrix -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang -Ofast -fenable-matrix -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang -Os -fenable-matrix -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang -Oz -fenable-matrix -S -emit-llvm %s -o - | FileCheck %s - -// Smoke test that the matrix intrinsics are lowered at any optimisation level. - -// FIXME: this fails with the NPM: -// -// %clang -O0 -fenable-matrix -S -emit-llvm %s -o - | FileCheck %s - -typedef float m4x4_t __attribute__((matrix_type(4, 4))); - -m4x4_t f(m4x4_t a, m4x4_t b, m4x4_t c) { - // - // CHECK-LABEL: f( - // CHECK-NOT: @llvm.matrix - // CHECK: } - // - return a + b * c; -} From ea4758a125298cc25639007509a8012f2f71fb00 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 17 Jul 2020 11:24:29 -0700 Subject: [PATCH 677/771] [flang] Rework read/write permission management for runtime file opening Anonymous Fortran unit files (e.g., "./fort.7") need to be created O_RDWR so that they can be written, rewound, and read. Other files opened with no ACTION= specifier need to set read/write permissions based on the file, if it exists. Reviewed By: sscalpone Differential Revision: https://reviews.llvm.org/D84063 --- flang/runtime/file.cpp | 110 +++++++++++++++++++++++--------------- flang/runtime/file.h | 8 ++- flang/runtime/io-api.cpp | 18 +++---- flang/runtime/io-stmt.cpp | 3 +- flang/runtime/io-stmt.h | 4 +- flang/runtime/unit.cpp | 15 ++---- flang/runtime/unit.h | 4 +- 7 files changed, 92 insertions(+), 70 deletions(-) diff --git a/flang/runtime/file.cpp b/flang/runtime/file.cpp index 19c86a9d4b82f..341702df995b8 100644 --- a/flang/runtime/file.cpp +++ b/flang/runtime/file.cpp @@ -57,63 +57,86 @@ static int openfile_mkstemp(IoErrorHandler &handler) { return fd; } -void OpenFile::Open( - OpenStatus status, Position position, IoErrorHandler &handler) { - int flags{mayRead_ ? mayWrite_ ? O_RDWR : O_RDONLY : O_WRONLY}; - switch (status) { - case OpenStatus::Old: - if (fd_ >= 0) { - return; +void OpenFile::Open(OpenStatus status, std::optional action, + Position position, IoErrorHandler &handler) { + if (fd_ >= 0 && + (status == OpenStatus::Old || status == OpenStatus::Unknown)) { + return; + } + if (fd_ >= 0) { + if (fd_ <= 2) { + // don't actually close a standard file descriptor, we might need it + } else { + if (::close(fd_) != 0) { + handler.SignalErrno(); + } } - knownSize_.reset(); - break; - case OpenStatus::New: - flags |= O_CREAT | O_EXCL; - knownSize_ = 0; - break; - case OpenStatus::Scratch: + fd_ = -1; + } + if (status == OpenStatus::Scratch) { if (path_.get()) { handler.SignalError("FILE= must not appear with STATUS='SCRATCH'"); path_.reset(); } + if (!action) { + action = Action::ReadWrite; + } fd_ = openfile_mkstemp(handler); - knownSize_ = 0; - return; - case OpenStatus::Replace: - flags |= O_CREAT | O_TRUNC; - knownSize_ = 0; - break; - case OpenStatus::Unknown: - if (fd_ >= 0) { + } else { + if (!path_.get()) { + handler.SignalError( + "FILE= is required unless STATUS='OLD' and unit is connected"); return; } - flags |= O_CREAT; - knownSize_.reset(); - break; - } - // If we reach this point, we're opening a new file. - // TODO: Fortran shouldn't create a new file until the first WRITE. - if (fd_ >= 0) { - if (fd_ <= 2) { - // don't actually close a standard file descriptor, we might need it - } else if (::close(fd_) != 0) { - handler.SignalErrno(); + int flags{0}; + if (status != OpenStatus::Old) { + flags |= O_CREAT; + } + if (status == OpenStatus::New) { + flags |= O_EXCL; + } else if (status == OpenStatus::Replace) { + flags |= O_TRUNC; + } + if (!action) { + // Try to open read/write, back off to read-only on failure + fd_ = ::open(path_.get(), flags | O_RDWR, 0600); + if (fd_ >= 0) { + action = Action::ReadWrite; + } else { + action = Action::Read; + } + } + if (fd_ < 0) { + switch (*action) { + case Action::Read: + flags |= O_RDONLY; + break; + case Action::Write: + flags |= O_WRONLY; + break; + case Action::ReadWrite: + flags |= O_RDWR; + break; + } + fd_ = ::open(path_.get(), flags, 0600); + if (fd_ < 0) { + handler.SignalErrno(); + } } } - if (!path_.get()) { - handler.SignalError( - "FILE= is required unless STATUS='OLD' and unit is connected"); - return; - } - fd_ = ::open(path_.get(), flags, 0600); - if (fd_ < 0) { - handler.SignalErrno(); - } + RUNTIME_CHECK(handler, action.has_value()); pending_.reset(); if (position == Position::Append && !RawSeekToEnd()) { handler.SignalErrno(); } isTerminal_ = ::isatty(fd_) == 1; + mayRead_ = *action != Action::Write; + mayWrite_ = *action != Action::Read; + if (status == OpenStatus::Old || status == OpenStatus::Unknown) { + knownSize_.reset(); + } else { + knownSize_ = 0; + } } void OpenFile::Predefine(int fd) { @@ -124,6 +147,9 @@ void OpenFile::Predefine(int fd) { knownSize_.reset(); nextId_ = 0; pending_.reset(); + mayRead_ = fd == 0; + mayWrite_ = fd != 0; + mayPosition_ = false; } void OpenFile::Close(CloseStatus status, IoErrorHandler &handler) { diff --git a/flang/runtime/file.h b/flang/runtime/file.h index 17a5e910ecae8..1d25a91558a4c 100644 --- a/flang/runtime/file.h +++ b/flang/runtime/file.h @@ -21,6 +21,7 @@ namespace Fortran::runtime::io { enum class OpenStatus { Old, New, Scratch, Replace, Unknown }; enum class CloseStatus { Keep, Delete }; enum class Position { AsIs, Rewind, Append }; +enum class Action { Read, Write, ReadWrite }; class OpenFile { public: @@ -30,19 +31,16 @@ class OpenFile { void set_path(OwningPtr &&, std::size_t bytes); std::size_t pathLength() const { return pathLength_; } bool mayRead() const { return mayRead_; } - void set_mayRead(bool yes) { mayRead_ = yes; } bool mayWrite() const { return mayWrite_; } - void set_mayWrite(bool yes) { mayWrite_ = yes; } + bool mayPosition() const { return mayPosition_; } bool mayAsynchronous() const { return mayAsynchronous_; } void set_mayAsynchronous(bool yes) { mayAsynchronous_ = yes; } - bool mayPosition() const { return mayPosition_; } - void set_mayPosition(bool yes) { mayPosition_ = yes; } FileOffset position() const { return position_; } bool isTerminal() const { return isTerminal_; } std::optional knownSize() const { return knownSize_; } bool IsOpen() const { return fd_ >= 0; } - void Open(OpenStatus, Position, IoErrorHandler &); + void Open(OpenStatus, std::optional, Position, IoErrorHandler &); void Predefine(int fd); void Close(CloseStatus, IoErrorHandler &); diff --git a/flang/runtime/io-api.cpp b/flang/runtime/io-api.cpp index 0bd827bc53aa2..2f077e1f9ff8f 100644 --- a/flang/runtime/io-api.cpp +++ b/flang/runtime/io-api.cpp @@ -563,31 +563,31 @@ bool IONAME(SetAction)(Cookie cookie, const char *keyword, std::size_t length) { io.GetIoErrorHandler().Crash( "SetAction() called when not in an OPEN statement"); } - bool mayRead{true}; - bool mayWrite{true}; + std::optional action; static const char *keywords[]{"READ", "WRITE", "READWRITE", nullptr}; switch (IdentifyValue(keyword, length, keywords)) { case 0: - mayWrite = false; + action = Action::Read; break; case 1: - mayRead = false; + action = Action::Write; break; case 2: + action = Action::ReadWrite; break; default: open->SignalError(IostatErrorInKeyword, "Invalid ACTION='%.*s'", static_cast(length), keyword); return false; } - if (mayRead != open->unit().mayRead() || - mayWrite != open->unit().mayWrite()) { - if (open->wasExtant()) { + RUNTIME_CHECK(io.GetIoErrorHandler(), action.has_value()); + if (open->wasExtant()) { + if ((*action != Action::Write) != open->unit().mayRead() || + (*action != Action::Read) != open->unit().mayWrite()) { open->SignalError("ACTION= may not be changed on an open unit"); } - open->unit().set_mayRead(mayRead); - open->unit().set_mayWrite(mayWrite); } + open->set_action(*action); return true; } diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 0681da215d1e4..70fb3f9350bc8 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -165,7 +165,8 @@ int OpenStatementState::EndIoStatement() { if (wasExtant_ && status_ != OpenStatus::Old) { SignalError("OPEN statement for connected unit must have STATUS='OLD'"); } - unit().OpenUnit(status_, position_, std::move(path_), pathLength_, *this); + unit().OpenUnit( + status_, action_, position_, std::move(path_), pathLength_, *this); return ExternalIoStatementBase::EndIoStatement(); } diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index 066391bd15664..6f5ca2c481128 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -294,15 +294,17 @@ class OpenStatementState : public ExternalIoStatementBase { : ExternalIoStatementBase{unit, sourceFile, sourceLine}, wasExtant_{ wasExtant} {} bool wasExtant() const { return wasExtant_; } - void set_status(OpenStatus status) { status_ = status; } + void set_status(OpenStatus status) { status_ = status; } // STATUS= void set_path(const char *, std::size_t, int kind); // FILE= void set_position(Position position) { position_ = position; } // POSITION= + void set_action(Action action) { action_ = action; } // ACTION= int EndIoStatement(); private: bool wasExtant_; OpenStatus status_{OpenStatus::Unknown}; Position position_{Position::AsIs}; + std::optional action_; OwningPtr path_; std::size_t pathLength_; }; diff --git a/flang/runtime/unit.cpp b/flang/runtime/unit.cpp index cf20d7cd81c66..c6af53e6ec223 100644 --- a/flang/runtime/unit.cpp +++ b/flang/runtime/unit.cpp @@ -64,7 +64,8 @@ ExternalFileUnit &ExternalFileUnit::LookUpOrCreateAnonymous( IoErrorHandler handler{terminator}; result.OpenUnit( dir == Direction::Input ? OpenStatus::Old : OpenStatus::Replace, - Position::Rewind, std::move(path), std::strlen(path.get()), handler); + Action::ReadWrite, Position::Rewind, std::move(path), + std::strlen(path.get()), handler); result.isUnformatted = isUnformatted; } return result; @@ -87,8 +88,8 @@ int ExternalFileUnit::NewUnit(const Terminator &terminator) { return GetUnitMap().NewUnit(terminator).unitNumber(); } -void ExternalFileUnit::OpenUnit(OpenStatus status, Position position, - OwningPtr &&newPath, std::size_t newPathLength, +void ExternalFileUnit::OpenUnit(OpenStatus status, std::optional action, + Position position, OwningPtr &&newPath, std::size_t newPathLength, IoErrorHandler &handler) { if (IsOpen()) { if (status == OpenStatus::Old && @@ -105,7 +106,7 @@ void ExternalFileUnit::OpenUnit(OpenStatus status, Position position, Close(CloseStatus::Keep, handler); } set_path(std::move(newPath), newPathLength); - Open(status, position, handler); + Open(status, action, position, handler); auto totalBytes{knownSize()}; if (access == Access::Direct) { if (!isFixedRecordLength || !recordLength) { @@ -186,16 +187,10 @@ UnitMap &ExternalFileUnit::GetUnitMap() { unitMap = New{terminator}().release(); ExternalFileUnit &out{ExternalFileUnit::CreateNew(6, terminator)}; out.Predefine(1); - out.set_mayRead(false); - out.set_mayWrite(true); - out.set_mayPosition(false); out.SetDirection(Direction::Output, handler); defaultOutput = &out; ExternalFileUnit &in{ExternalFileUnit::CreateNew(5, terminator)}; in.Predefine(0); - in.set_mayRead(true); - in.set_mayWrite(false); - in.set_mayPosition(false); in.SetDirection(Direction::Input, handler); defaultInput = ∈ // TODO: Set UTF-8 mode from the environment diff --git a/flang/runtime/unit.h b/flang/runtime/unit.h index f0edeedef0812..d2d2dce035f14 100644 --- a/flang/runtime/unit.h +++ b/flang/runtime/unit.h @@ -48,8 +48,8 @@ class ExternalFileUnit : public ConnectionState, static void CloseAll(IoErrorHandler &); static void FlushAll(IoErrorHandler &); - void OpenUnit(OpenStatus, Position, OwningPtr &&path, - std::size_t pathLength, IoErrorHandler &); + void OpenUnit(OpenStatus, std::optional, Position, + OwningPtr &&path, std::size_t pathLength, IoErrorHandler &); void CloseUnit(CloseStatus, IoErrorHandler &); void DestroyClosed(); From db15b8ab90793e3707f72e7668c3844922fdf356 Mon Sep 17 00:00:00 2001 From: Teresa Johnson Date: Fri, 17 Jul 2020 14:48:28 -0700 Subject: [PATCH 678/771] [compiler-rt][asan][hwasan] Fix Fuchsia build Fix build failure in Fuchsia build from refactoring in 5d2be1a18845c528d3e86f7efcc59872e4a757c3 Guard the moved versions of ReserveShadowMemoryRange and ProtectGap the same way they were in the asan code originally (not for Fuchsia or RTEMS). Otherwise we end up with unsats as they invoke functions not defined there. --- compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp index ddd688bb2dca4..047c5a17ea6e7 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_libcdep.cpp @@ -139,6 +139,8 @@ uptr ReservedAddressRange::InitAligned(uptr size, uptr align, return start; } +#if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS + // Reserve memory range [beg, end]. // We need to use inclusive range because end+1 may not be representable. void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name, @@ -188,6 +190,8 @@ void ProtectGap(uptr addr, uptr size, uptr zero_base_shadow_start, Die(); } +#endif // !SANITIZER_FUCHSIA && !SANITIZER_RTEMS + } // namespace __sanitizer SANITIZER_INTERFACE_WEAK_DEF(void, __sanitizer_sandbox_on_notify, From 09fe0c5ab9ca5846d6cb625e9be47fdcfe49b93c Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Fri, 17 Jul 2020 17:54:01 -0400 Subject: [PATCH 679/771] [OpenMP] Add Additional Function Attribute Information to OMPKinds.def Summary: This patch adds more function attribute information to the runtime function definitions in OMPKinds.def. The goal is to provide sufficient information about OpenMP runtime functions to perform more optimizations on OpenMP code. Reviewers: jdoerfert Subscribers: aaron.ballman cfe-commits yaxunl guansong sstefan1 llvm-commits Tags: #OpenMP #clang #llvm Differential Revision: https://reviews.llvm.org/D81031 --- .../include/llvm/Frontend/OpenMP/OMPKinds.def | 669 +++++++++------- llvm/test/Transforms/OpenMP/add_attributes.ll | 745 ++++++++++++------ .../Transforms/OpenMP/parallel_deletion.ll | 2 +- 3 files changed, 896 insertions(+), 520 deletions(-) diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index 0dc2b34f2e4d6..bb476f6a34d4e 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -383,7 +383,8 @@ __OMP_RTL(__kmpc_push_proc_bind, false, Void, IdentPtr, Int32, /* Int */ Int32) __OMP_RTL(__kmpc_serialized_parallel, false, Void, IdentPtr, Int32) __OMP_RTL(__kmpc_end_serialized_parallel, false, Void, IdentPtr, Int32) __OMP_RTL(__kmpc_omp_reg_task_with_affinity, false, Int32, IdentPtr, Int32, - Int8Ptr, Int32, Int8Ptr) + /* kmp_task_t */ VoidPtr, Int32, + /* kmp_task_affinity_info_t */ VoidPtr) __OMP_RTL(omp_get_thread_num, false, Int32, ) __OMP_RTL(omp_get_num_threads, false, Int32, ) @@ -430,8 +431,7 @@ __OMP_RTL(__kmpc_reduce, false, Int32, IdentPtr, Int32, Int32, SizeTy, VoidPtr, ReduceFunctionPtr, KmpCriticalNamePtrTy) __OMP_RTL(__kmpc_reduce_nowait, false, Int32, IdentPtr, Int32, Int32, SizeTy, VoidPtr, ReduceFunctionPtr, KmpCriticalNamePtrTy) -__OMP_RTL(__kmpc_end_reduce, false, Void, IdentPtr, Int32, - KmpCriticalNamePtrTy) +__OMP_RTL(__kmpc_end_reduce, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy) __OMP_RTL(__kmpc_end_reduce_nowait, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy) @@ -514,10 +514,10 @@ __OMP_RTL(__kmpc_taskloop, false, Void, IdentPtr, /* Int */ Int32, VoidPtr, /* Int */ Int32, Int64, VoidPtr) __OMP_RTL(__kmpc_omp_target_task_alloc, false, /* kmp_task_t */ VoidPtr, IdentPtr, Int32, Int32, SizeTy, SizeTy, TaskRoutineEntryPtr, Int64) -__OMP_RTL(__kmpc_taskred_modifier_init, false, VoidPtr, IdentPtr, - /* Int */ Int32, /* Int */ Int32, /* Int */ Int32, VoidPtr) -__OMP_RTL(__kmpc_taskred_init, false, VoidPtr, /* Int */ Int32, - /* Int */ Int32, VoidPtr) +__OMP_RTL(__kmpc_taskred_modifier_init, false, /* kmp_taskgroup */ VoidPtr, + IdentPtr, /* Int */ Int32, /* Int */ Int32, /* Int */ Int32, VoidPtr) +__OMP_RTL(__kmpc_taskred_init, false, /* kmp_taskgroup */ VoidPtr, + /* Int */ Int32, /* Int */ Int32, VoidPtr) __OMP_RTL(__kmpc_task_reduction_modifier_fini, false, Void, IdentPtr, /* Int */ Int32, /* Int */ Int32) __OMP_RTL(__kmpc_task_reduction_get_th_data, false, VoidPtr, Int32, VoidPtr, @@ -594,7 +594,9 @@ __OMP_RTL(__last, false, Void, ) #undef __OMP_RTL #undef OMP_RTL +#define ParamAttrs(...) ArrayRef({__VA_ARGS__}) #define EnumAttr(Kind) Attribute::get(Ctx, Attribute::AttrKind::Kind) +#define EnumAttrInt(Kind, N) Attribute::get(Ctx, Attribute::AttrKind::Kind, N) #define AttributeSet(...) \ AttributeSet::get(Ctx, ArrayRef({__VA_ARGS__})) @@ -607,19 +609,88 @@ __OMP_RTL(__last, false, Void, ) __OMP_ATTRS_SET(GetterAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(ReadOnly), - EnumAttr(NoSync), EnumAttr(NoFree), EnumAttr(InaccessibleMemOnly)) + EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(InaccessibleMemOnly), + EnumAttr(WillReturn)) : AttributeSet(EnumAttr(NoUnwind))) __OMP_ATTRS_SET(GetterArgWriteAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(NoFree), EnumAttr(InaccessibleMemOrArgMemOnly)) + EnumAttr(NoFree), + EnumAttr(InaccessibleMemOrArgMemOnly), + EnumAttr(WillReturn)) : AttributeSet(EnumAttr(NoUnwind))) __OMP_ATTRS_SET(SetterAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(WriteOnly), - EnumAttr(NoSync), EnumAttr(NoFree), EnumAttr(InaccessibleMemOnly)) + EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(InaccessibleMemOnly), + EnumAttr(WillReturn)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(DefaultAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), + EnumAttr(WillReturn), EnumAttr(NoFree)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(BarrierAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(InaccessibleArgOnlyAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), + EnumAttr(InaccessibleMemOrArgMemOnly), + EnumAttr(WillReturn), EnumAttr(NoFree)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(InaccessibleOnlyAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), + EnumAttr(InaccessibleMemOnly), + EnumAttr(WillReturn), EnumAttr(NoFree)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(AllocAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), + EnumAttr(WillReturn)) : AttributeSet(EnumAttr(NoUnwind))) +__OMP_ATTRS_SET(ForkAttrs, OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(ReadOnlyPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(ReadOnly), EnumAttr(NoFree), + EnumAttr(NoCapture)) + : AttributeSet()) + +__OMP_ATTRS_SET(WriteOnlyPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(WriteOnly), EnumAttr(NoFree), + EnumAttr(NoCapture)) + : AttributeSet()) + +__OMP_ATTRS_SET(ArgPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoCapture), EnumAttr(NoFree)) + : AttributeSet()) + +__OMP_ATTRS_SET(ReturnPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoAlias)) + : AttributeSet()) + +__OMP_ATTRS_SET(ReturnAlignedPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoAlias), EnumAttrInt(Alignment, 8), + EnumAttrInt(DereferenceableOrNull, 8)) + : AttributeSet()) + #undef __OMP_ATTRS_SET #undef OMP_ATTRS_SET @@ -630,295 +701,309 @@ __OMP_ATTRS_SET(SetterAttrs, #define __OMP_RTL_ATTRS(Name, FnAttrSet, RetAttrSet, ArgAttrSets) \ OMP_RTL_ATTRS(OMPRTL_##Name, FnAttrSet, RetAttrSet, ArgAttrSets) -__OMP_RTL_ATTRS(__kmpc_barrier, AttributeSet(), AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_cancel, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_cancel_barrier, AttributeSet(), AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_flush, AttributeSet(), AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_global_thread_num, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_fork_call, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_taskwait, AttributeSet(), AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_taskyield, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_push_num_threads, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_push_proc_bind, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_serialized_parallel, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_serialized_parallel, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(omp_get_thread_num, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_num_threads, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_max_threads, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_in_parallel, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_dynamic, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_cancellation, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_nested, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_schedule, GetterArgWriteAttrs, AttributeSet(), - ArrayRef( - {AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)), - AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly))})) -__OMP_RTL_ATTRS(omp_get_thread_limit, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_barrier, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_cancel, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_cancel_barrier, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_flush, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_global_thread_num, GetterAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_fork_call, ForkAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_taskwait, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_taskyield, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_push_num_threads, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_push_proc_bind, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_serialized_parallel, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end_serialized_parallel, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_reg_task_with_affinity, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs, + AttributeSet(), ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(omp_get_thread_num, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_num_threads, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_max_threads, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_in_parallel, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_dynamic, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_cancellation, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_nested, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS( + omp_get_schedule, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)), + AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)))) +__OMP_RTL_ATTRS(omp_get_thread_limit, GetterAttrs, AttributeSet(), ParamAttrs()) __OMP_RTL_ATTRS(omp_get_supported_active_levels, GetterAttrs, AttributeSet(), - {}) -__OMP_RTL_ATTRS(omp_get_max_active_levels, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_level, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_ancestor_thread_num, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_team_size, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_active_level, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_in_final, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_proc_bind, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_num_places, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_num_procs, GetterAttrs, AttributeSet(), {}) + ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_max_active_levels, GetterAttrs, AttributeSet(), + ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_level, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_ancestor_thread_num, GetterAttrs, AttributeSet(), + ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_team_size, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_active_level, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_in_final, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_proc_bind, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_num_places, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_num_procs, GetterAttrs, AttributeSet(), ParamAttrs()) __OMP_RTL_ATTRS(omp_get_place_proc_ids, GetterArgWriteAttrs, AttributeSet(), - ArrayRef({AttributeSet(), - AttributeSet(EnumAttr(NoCapture), - EnumAttr(WriteOnly))})) -__OMP_RTL_ATTRS(omp_get_place_num, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_partition_num_places, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_partition_place_nums, GetterAttrs, AttributeSet(), {}) - -__OMP_RTL_ATTRS(omp_set_num_threads, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_set_dynamic, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_set_nested, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_set_schedule, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_set_max_active_levels, SetterAttrs, AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_master, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_master, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_critical, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_critical_with_hint, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_critical, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_begin, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_reduce, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_reduce_nowait, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_reduce, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_reduce_nowait, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_ordered, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_ordered, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_for_static_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_for_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_for_static_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_for_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_for_static_fini, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_team_static_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_team_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_team_static_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_team_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_single, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_single, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_omp_task_alloc, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_task, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_taskgroup, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_taskgroup, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_task_begin_if0, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_task_complete_if0, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_task_with_deps, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_taskloop, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_target_task_alloc, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_taskred_modifier_init, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_taskred_init, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_fini, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_reduction_get_th_data, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_reduction_init, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_init, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_proxy_task_completed_ooo, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_omp_wait_deps, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_cancellationpoint, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_fork_teams, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_push_num_teams, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_copyprivate, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_threadprivate_cached, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_threadprivate_register, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_doacross_init, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_doacross_post, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_doacross_wait, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_doacross_fini, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_alloc, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_free, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_init_allocator, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_destroy_allocator, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_push_target_tripcount, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_teams_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_teams_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_register_requires, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_begin_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_begin_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_end_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_end_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_update_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_update_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_mapper_num_components, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_push_mapper_component, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_allow_completion_event, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) + ParamAttrs(AttributeSet(), AttributeSet(EnumAttr(NoCapture), + EnumAttr(WriteOnly)))) +__OMP_RTL_ATTRS(omp_get_place_num, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_partition_num_places, GetterAttrs, AttributeSet(), + ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_partition_place_nums, GetterAttrs, AttributeSet(), + ParamAttrs()) + +__OMP_RTL_ATTRS(omp_set_num_threads, SetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_set_dynamic, SetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_set_nested, SetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_set_schedule, SetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_set_max_active_levels, SetterAttrs, AttributeSet(), + ParamAttrs()) + +__OMP_RTL_ATTRS(__kmpc_master, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end_master, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_critical, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_critical_with_hint, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_end_critical, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) + +__OMP_RTL_ATTRS(__kmpc_begin, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_reduce, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), ReadOnlyPtrAttrs, AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_reduce_nowait, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), ReadOnlyPtrAttrs, AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_end_reduce, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_end_reduce_nowait, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) + +__OMP_RTL_ATTRS(__kmpc_ordered, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end_ordered, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_for_static_init_4, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_for_static_init_4u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_for_static_init_8, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_for_static_init_8u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_for_static_fini, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4u, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8u, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_4, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_4u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_8, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_8u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_4, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_4u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_8, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_8u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4u, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8u, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_team_static_init_4, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_team_static_init_4u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_team_static_init_8, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_team_static_init_8u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4u, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8u, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + ArgPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_single, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end_single, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_omp_task_alloc, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_task, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_end_taskgroup, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_taskgroup, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_task_begin_if0, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_task_complete_if0, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_task_with_deps, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), ReadOnlyPtrAttrs, AttributeSet(), + ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_taskloop, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet(), AttributeSet(), + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_omp_target_task_alloc, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), AttributeSet(), ReadOnlyPtrAttrs, + AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_taskred_modifier_init, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_taskred_init, DefaultAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_fini, BarrierAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_task_reduction_get_th_data, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_task_reduction_init, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_init, DefaultAttrs, + ReturnPtrAttrs, ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_proxy_task_completed_ooo, DefaultAttrs, AttributeSet(), + ParamAttrs()) + +__OMP_RTL_ATTRS(__kmpc_omp_wait_deps, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_cancellationpoint, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_fork_teams, ForkAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_push_num_teams, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_copyprivate, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_threadprivate_cached, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_threadprivate_register, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs, + ReadOnlyPtrAttrs, ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_doacross_init, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_doacross_post, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_doacross_wait, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_doacross_fini, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_alloc, DefaultAttrs, ReturnPtrAttrs, {}) +__OMP_RTL_ATTRS(__kmpc_free, AllocAttrs, AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_init_allocator, DefaultAttrs, ReturnPtrAttrs, {}) +__OMP_RTL_ATTRS(__kmpc_destroy_allocator, AllocAttrs, AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_push_target_tripcount, SetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_nowait_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_teams_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_teams_nowait_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_register_requires, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_begin_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_begin_nowait_mapper, ForkAttrs, + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_end_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_end_nowait_mapper, ForkAttrs, + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_update_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_update_nowait_mapper, ForkAttrs, + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_mapper_num_components, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_push_mapper_component, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_task_allow_completion_event, DefaultAttrs, + ReturnPtrAttrs, ParamAttrs(ReadOnlyPtrAttrs)) #undef __OMP_RTL_ATTRS #undef OMP_RTL_ATTRS #undef AttributeSet #undef EnumAttr +#undef EnumAttrInt +#undef ParamAttrs ///} diff --git a/llvm/test/Transforms/OpenMP/add_attributes.ll b/llvm/test/Transforms/OpenMP/add_attributes.ll index 6e10613ed43c3..e92447d79feac 100644 --- a/llvm/test/Transforms/OpenMP/add_attributes.ll +++ b/llvm/test/Transforms/OpenMP/add_attributes.ll @@ -890,373 +890,373 @@ declare void @__kmpc_proxy_task_completed_ooo(i8*) ; CHECK: ; Function Attrs: nounwind ; CHECK-NEXT: declare dso_local i32 @omp_get_supported_active_levels() #0 -; CHECK-NOT: Function Attrs -; CHECK: declare void @__kmpc_barrier(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_barrier(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) #0 -; CHECK-NOT: Function Attrs -; CHECK: declare i32 @__kmpc_cancel_barrier(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_cancel_barrier(%struct.ident_t*, i32) #0 -; CHECK-NOT: Function Attrs -; CHECK: declare void @__kmpc_flush(%struct.ident_t*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_flush(%struct.ident_t*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) #0 -; CHECK-NOT: Function Attrs -; CHECK: declare i32 @__kmpc_omp_taskwait(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_taskwait(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare i32 @__kmpc_master(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_master(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_end_master(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_master(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_critical(%struct.ident_t*, i32, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_critical(%struct.ident_t*, i32, [8 x i32]*) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t*, i32, [8 x i32]*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t*, i32, [8 x i32]*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_end_critical(%struct.ident_t*, i32, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_critical(%struct.ident_t*, i32, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_begin(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_begin(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end(%struct.ident_t*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end(%struct.ident_t*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t*, i32, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t*, i32, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t*, i32, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t*, i32, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_ordered(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_ordered(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_single(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_single(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_single(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_single(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_omp_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_omp_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t*, i32, i32, i32, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t*, i32, i32, i32, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t*, i32, i32, i32, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t*, i32, i32, i32, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t*, i32, i32, i64, i64, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t*, i32, i32, i64, i64, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t*, i32, i32, i64, i64, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t*, i32, i32, i64, i64, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t*, i32, i8*, i32, i8*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t*, i32, i8*, i32, i8*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t*, i32, i32, i8*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t*, i32, i32, i8*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t*, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t*, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_taskloop(%struct.ident_t*, i32, i8*, i32, i64*, i64*, i64, i32, i32, i64, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_taskloop(%struct.ident_t*, i32, i8*, i32, i64*, i64*, i64, i32, i32, i64, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_omp_target_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_omp_target_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_taskred_modifier_init(%struct.ident_t*, i32, i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_taskred_modifier_init(%struct.ident_t*, i32, i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t*, i32, i64, i8*, void (i8*, i8*)*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t*, i32, i64, i8*, void (i8*, i8*)*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_threadprivate_cached(%struct.ident_t*, i32, i8*, i64, i8***) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_threadprivate_cached(%struct.ident_t*, i32, i8*, i64, i8***) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t*, i8*, i8* (i8*)*, i8* (i8*, i8*)*, void (i8*)*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t*, i8*, i8* (i8*)*, i8* (i8*, i8*)*, void (i8*)*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t*, i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t*, i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t*, i32, i64*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t*, i32, i64*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t*, i32, i64*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t*, i32, i64*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_alloc(i32, i64, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_alloc(i32, i64, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_free(i32, i8*, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_free(i32, i8*, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_register_requires(i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_register_requires(i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i64 @__tgt_mapper_num_components(i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i64 @__tgt_mapper_num_components(i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_allow_completion_event(%struct.ident_t*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_allow_completion_event(%struct.ident_t*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_init(i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_init(i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) #0 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_num_threads(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_dynamic(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_nested(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_max_active_levels(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_schedule(i32, i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_num_threads() #1 ; OPTIMISTIC-NOT: Function Attrs ; OPTIMISTIC: declare dso_local void @use_int(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_dynamic() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_nested() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_max_threads() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_thread_num() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_num_procs() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_in_parallel() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_in_final() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_active_level() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_level() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_ancestor_thread_num(i32) #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_team_size(i32) #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_thread_limit() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_max_active_levels() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn ; OPTIMISTIC-NEXT: declare dso_local void @omp_get_schedule(i32* nocapture writeonly, i32* nocapture writeonly) #2 ; OPTIMISTIC-NOT: Function Attrs @@ -1418,8 +1418,299 @@ declare void @__kmpc_proxy_task_completed_ooo(i8*) ; OPTIMISTIC-NOT: Function Attrs ; OPTIMISTIC: declare dso_local i32 @omp_pause_resource_all(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_supported_active_levels() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly -; OPTIMISTIC-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_fork_call(%struct.ident_t* nocapture nofree readonly, i32, void (i32*, i32*, ...)* nocapture nofree readonly, ...) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_taskwait(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_master(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_end_master(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_critical(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_critical(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_begin(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_end(%struct.ident_t* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_ordered(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__kmpc_single(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_single(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_omp_task_alloc(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i32 (i32, i8*)* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64, i64, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64, i64, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t* nocapture nofree readonly, i32, i8*, i32, i8* nocapture nofree readonly, i32, i8* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t* nocapture nofree readonly, i32, i32, i8* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t* nocapture nofree readonly, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t* nocapture nofree readonly, i32, void (i32*, i32*, ...)* nocapture nofree readonly, ...) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_taskloop(%struct.ident_t* nocapture nofree readonly, i32, i8*, i32, i64* nocapture nofree, i64* nocapture nofree, i64, i32, i32, i64, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_omp_target_task_alloc(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i32 (i32, i8*)* nocapture nofree readonly, i64) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_taskred_modifier_init(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t* nocapture nofree readonly, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_threadprivate_cached(%struct.ident_t* nocapture nofree readonly, i32, i8*, i64, i8***) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t* nocapture nofree readonly, i8*, i8* (i8*)* nocapture nofree readonly, i8* (i8*, i8*)* nocapture nofree readonly, void (i8*)* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t* nocapture nofree readonly, i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t* nocapture nofree readonly, i32, i64* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t* nocapture nofree readonly, i32, i64* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_alloc(i32, i64, i8*) + +; OPTIMISTIC: ; Function Attrs: nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_free(i32, i8*, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) + +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly +; OPTIMISTIC-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_register_requires(i64) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i64 @__tgt_mapper_num_components(i8*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_allow_completion_event(%struct.ident_t* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_init(i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) diff --git a/llvm/test/Transforms/OpenMP/parallel_deletion.ll b/llvm/test/Transforms/OpenMP/parallel_deletion.ll index 4d2f8e7cbc5e8..07976660546f8 100644 --- a/llvm/test/Transforms/OpenMP/parallel_deletion.ll +++ b/llvm/test/Transforms/OpenMP/parallel_deletion.ll @@ -393,7 +393,7 @@ entry: define internal void @.omp.reduction.reduction_func(i8* %arg, i8* %arg1) { ; CHECK-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func -; CHECK-SAME: (i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #10 +; CHECK-SAME: (i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #{{[0-9]+}} ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP:%.*]] = bitcast i8* [[ARG1]] to i32** ; CHECK-NEXT: [[TMP2:%.*]] = load i32*, i32** [[TMP]], align 8 From ae08dbc67326eaebefef7f4401767ddf7583c9b0 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 17 Jul 2020 14:58:01 -0700 Subject: [PATCH 680/771] Temporarily Revert "[InlineAdvisor] New inliner advisor to replay inlining from optimization remarks" as it is failing the inline-replay.ll test as well as sanitizers/Werror from returning a stack local variable. This reverts commit 029946b112684c27b27f7c2d7554f22b33ae1e0b. --- llvm/include/llvm/Analysis/InlineAdvisor.h | 3 - .../llvm/Analysis/ReplayInlineAdvisor.h | 37 ------ llvm/lib/Analysis/CMakeLists.txt | 1 - llvm/lib/Analysis/InlineAdvisor.cpp | 25 ---- llvm/lib/Analysis/ReplayInlineAdvisor.cpp | 61 --------- llvm/lib/Transforms/IPO/SampleProfile.cpp | 37 +----- .../SampleProfile/Inputs/inline-replay.txt | 2 - .../Transforms/SampleProfile/inline-replay.ll | 122 ------------------ 8 files changed, 4 insertions(+), 284 deletions(-) delete mode 100644 llvm/include/llvm/Analysis/ReplayInlineAdvisor.h delete mode 100644 llvm/lib/Analysis/ReplayInlineAdvisor.cpp delete mode 100644 llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt delete mode 100644 llvm/test/Transforms/SampleProfile/inline-replay.ll diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h index a0ff09679dfed..3480d93385a8e 100644 --- a/llvm/include/llvm/Analysis/InlineAdvisor.h +++ b/llvm/include/llvm/Analysis/InlineAdvisor.h @@ -226,9 +226,6 @@ void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, bool ForProfileContext = false, const char *PassName = nullptr); -/// get call site location as string -StringRef getCallSiteLocation(DebugLoc DLoc); - /// Add location info to ORE message. void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc); diff --git a/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h b/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h deleted file mode 100644 index e312d59a9f87b..0000000000000 --- a/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h +++ /dev/null @@ -1,37 +0,0 @@ -//===- ReplayInlineAdvisor.h - Replay Inline Advisor interface -*- C++ --*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -#ifndef LLVM_REPLAYINLINEADVISOR_H_ -#define LLVM_REPLAYINLINEADVISOR_H_ - -#include "llvm/ADT/StringSet.h" -#include "llvm/Analysis/InlineAdvisor.h" -#include "llvm/IR/LLVMContext.h" - -namespace llvm { -class BasicBlock; -class CallBase; -class Function; -class Module; -class OptimizationRemarkEmitter; - -/// Replay inline advisor that uses optimization remarks from inlining of -/// previous build to guide current inlining. This is useful for inliner tuning. -class ReplayInlineAdvisor : public InlineAdvisor { -public: - ReplayInlineAdvisor(FunctionAnalysisManager &FAM, LLVMContext &Context, - StringRef RemarksFile); - std::unique_ptr getAdvice(CallBase &CB) override; - bool areReplayRemarksLoaded() const { return HasReplayRemarks; } - -private: - StringSet<> InlineSitesFromRemarks; - bool HasReplayRemarks = false; -}; -} // namespace llvm -#endif // LLVM_REPLAYINLINEADVISOR_H_ \ No newline at end of file diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 8f10bac588e52..703623396d96a 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -117,7 +117,6 @@ add_llvm_component_library(LLVMAnalysis RegionInfo.cpp RegionPass.cpp RegionPrinter.cpp - ReplayInlineAdvisor.cpp ScalarEvolution.cpp ScalarEvolutionAliasAnalysis.cpp ScalarEvolutionDivision.cpp diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp index fedc5282ee646..e18f681278d3a 100644 --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -365,31 +365,6 @@ llvm::shouldInline(CallBase &CB, return IC; } -StringRef llvm::getCallSiteLocation(DebugLoc DLoc) { - std::ostringstream CallSiteLoc; - bool First = true; - for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) { - if (!First) - CallSiteLoc << " @ "; - // Note that negative line offset is actually possible, but we use - // unsigned int to match line offset representation in remarks so - // it's directly consumable by relay advisor. - uint32_t Offset = - DIL->getLine() - DIL->getScope()->getSubprogram()->getLine(); - uint32_t Discriminator = DIL->getBaseDiscriminator(); - StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName(); - if (Name.empty()) - Name = DIL->getScope()->getSubprogram()->getName(); - CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset); - if (Discriminator) { - CallSiteLoc << "." << llvm::utostr(Discriminator); - } - First = false; - } - - return CallSiteLoc.str(); -} - void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) { if (!DLoc.get()) return; diff --git a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp deleted file mode 100644 index c12b58021a606..0000000000000 --- a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//===- ReplayInlineAdvisor.cpp - Replay InlineAdvisor ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements ReplayInlineAdvisor that replays inline decision based -// on previous inline remarks from optimization remark log. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/InlineAdvisor.h" -#include "llvm/Analysis/ReplayInlineAdvisor.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Support/LineIterator.h" - -using namespace llvm; - -#define DEBUG_TYPE "inline-replay" - -ReplayInlineAdvisor::ReplayInlineAdvisor(FunctionAnalysisManager &FAM, - LLVMContext &Context, - StringRef RemarksFile) - : InlineAdvisor(FAM), HasReplayRemarks(false) { - auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(RemarksFile); - std::error_code EC = BufferOrErr.getError(); - if (EC) { - Context.emitError("Could not open remarks file: " + EC.message()); - return; - } - - // Example for inline remarks to parse: - // _Z3subii inlined into main [details] at callsite sum:1 @ main:3.1 - // We use the callsite string after `at callsite` to replay inlining. - line_iterator LineIt(*BufferOrErr.get(), /*SkipBlanks=*/true); - for (; !LineIt.is_at_eof(); ++LineIt) { - StringRef Line = *LineIt; - auto Pair = Line.split(" at callsite "); - if (Pair.second.empty()) - continue; - InlineSitesFromRemarks.insert(Pair.second); - } - HasReplayRemarks = true; -} - -std::unique_ptr ReplayInlineAdvisor::getAdvice(CallBase &CB) { - assert(HasReplayRemarks); - - Function &Caller = *CB.getCaller(); - auto &ORE = FAM.getResult(Caller); - - if (InlineSitesFromRemarks.empty()) - return std::make_unique(this, CB, ORE, false); - - StringRef CallSiteLoc = getCallSiteLocation(CB.getDebugLoc()); - bool InlineRecommended = InlineSitesFromRemarks.count(CallSiteLoc) > 0; - return std::make_unique(this, CB, ORE, InlineRecommended); -} diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index 7b5fc030cf88c..b6871e260532d 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -43,7 +43,6 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ProfileSummaryInfo.h" -#include "llvm/Analysis/ReplayInlineAdvisor.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/BasicBlock.h" @@ -171,13 +170,6 @@ static cl::opt SampleColdCallSiteThreshold( "sample-profile-cold-inline-threshold", cl::Hidden, cl::init(45), cl::desc("Threshold for inlining cold callsites")); -static cl::opt ProfileInlineReplayFile( - "sample-profile-inline-replay", cl::init(""), cl::value_desc("filename"), - cl::desc( - "Optimization remarks file containing inline remarks to be replayed " - "by inlining from sample profile loader."), - cl::Hidden); - namespace { using BlockWeightMap = DenseMap; @@ -327,7 +319,7 @@ class SampleProfileLoader { RemappingFilename(std::string(RemapName)), IsThinLTOPreLink(IsThinLTOPreLink) {} - bool doInitialization(Module &M, FunctionAnalysisManager *FAM = nullptr); + bool doInitialization(Module &M); bool runOnModule(Module &M, ModuleAnalysisManager *AM, ProfileSummaryInfo *_PSI, CallGraph *CG); @@ -481,9 +473,6 @@ class SampleProfileLoader { // overriden by -profile-sample-accurate or profile-sample-accurate // attribute. bool ProfAccForSymsInList; - - // External inline advisor used to replay inline decision from remarks. - std::unique_ptr ExternalInlineAdvisor; }; class SampleProfileLoaderLegacyPass : public ModulePass { @@ -909,16 +898,6 @@ SampleProfileLoader::findFunctionSamples(const Instruction &Inst) const { } bool SampleProfileLoader::inlineCallInstruction(CallBase &CB) { - if (ExternalInlineAdvisor) { - auto Advice = ExternalInlineAdvisor->getAdvice(CB); - if (!Advice->isInliningRecommended()) { - Advice->recordUnattemptedInlining(); - return false; - } - // Dummy record, we don't use it for replay. - Advice->recordInlining(); - } - Function *CalledFunction = CB.getCalledFunction(); assert(CalledFunction); DebugLoc DLoc = CB.getDebugLoc(); @@ -1026,7 +1005,7 @@ bool SampleProfileLoader::inlineHotFunctions( } } } - if (Hot || ExternalInlineAdvisor) { + if (Hot) { CIS.insert(CIS.begin(), AllCandidates.begin(), AllCandidates.end()); emitOptimizationRemarksForInlineCandidates(AllCandidates, F, true); } else { @@ -1839,8 +1818,7 @@ SampleProfileLoader::buildFunctionOrder(Module &M, CallGraph *CG) { return FunctionOrderList; } -bool SampleProfileLoader::doInitialization(Module &M, - FunctionAnalysisManager *FAM) { +bool SampleProfileLoader::doInitialization(Module &M) { auto &Ctx = M.getContext(); std::unique_ptr RemapReader; @@ -1865,13 +1843,6 @@ bool SampleProfileLoader::doInitialization(Module &M, NamesInProfile.insert(NameTable->begin(), NameTable->end()); } - if (FAM && !ProfileInlineReplayFile.empty()) { - ExternalInlineAdvisor = std::make_unique( - *FAM, Ctx, ProfileInlineReplayFile); - if (!ExternalInlineAdvisor->areReplayRemarksLoaded()) - ExternalInlineAdvisor.reset(); - } - return true; } @@ -2024,7 +1995,7 @@ PreservedAnalyses SampleProfileLoaderPass::run(Module &M, : ProfileRemappingFileName, IsThinLTOPreLink, GetAssumptionCache, GetTTI, GetTLI); - if (!SampleLoader.doInitialization(M, &FAM)) + if (!SampleLoader.doInitialization(M)) return PreservedAnalyses::all(); ProfileSummaryInfo *PSI = &AM.getResult(M); diff --git a/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt b/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt deleted file mode 100644 index 6842845d56554..0000000000000 --- a/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt +++ /dev/null @@ -1,2 +0,0 @@ -remark: calls.cc:10:0: _Z3sumii inlined into main to match profiling context with (cost=45, threshold=337) at callsite main:3.1 -remark: calls.cc:4:0: _Z3subii inlined into main to match profiling context with (cost=-5, threshold=337) at callsite _Z3sumii:1 @ main:3.1 diff --git a/llvm/test/Transforms/SampleProfile/inline-replay.ll b/llvm/test/Transforms/SampleProfile/inline-replay.ll deleted file mode 100644 index ecf6f51850f26..0000000000000 --- a/llvm/test/Transforms/SampleProfile/inline-replay.ll +++ /dev/null @@ -1,122 +0,0 @@ -;; Note that this needs new pass manager for now. Passing `-sample-profile-inline-replay` to legacy pass manager is a no-op. - -;; Check baseline inline decisions -; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline-topdown.prof -sample-profile-merge-inlinee -sample-profile-top-down-load -pass-remarks=inline -S 2>&1 | FileCheck -check-prefix=DEFAULT %s - -;; Check replay inline decisions -; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline-topdown.prof -sample-profile-inline-replay=%S/Inputs/inline-replay.txt -sample-profile-merge-inlinee -sample-profile-top-down-load -pass-remarks=inline -S 2>&1 | FileCheck -check-prefix=REPLAY %s - -@.str = private unnamed_addr constant [11 x i8] c"sum is %d\0A\00", align 1 - -define i32 @_Z3sumii(i32 %x, i32 %y) #0 !dbg !6 { -entry: - %x.addr = alloca i32, align 4 - %y.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - store i32 %y, i32* %y.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4, !dbg !8 - %tmp1 = load i32, i32* %y.addr, align 4, !dbg !8 - %add = add nsw i32 %tmp, %tmp1, !dbg !8 - %tmp2 = load i32, i32* %x.addr, align 4, !dbg !8 - %tmp3 = load i32, i32* %y.addr, align 4, !dbg !8 - %call = call i32 @_Z3subii(i32 %tmp2, i32 %tmp3), !dbg !8 - ret i32 %add, !dbg !8 -} - -define i32 @_Z3subii(i32 %x, i32 %y) #0 !dbg !9 { -entry: - %x.addr = alloca i32, align 4 - %y.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - store i32 %y, i32* %y.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4, !dbg !10 - %tmp1 = load i32, i32* %y.addr, align 4, !dbg !10 - %add = sub nsw i32 %tmp, %tmp1, !dbg !10 - ret i32 %add, !dbg !11 -} - -define i32 @main() #0 !dbg !12 { -entry: - %retval = alloca i32, align 4 - %s = alloca i32, align 4 - %i = alloca i32, align 4 - store i32 0, i32* %retval - store i32 0, i32* %i, align 4, !dbg !13 - br label %while.cond, !dbg !14 - -while.cond: ; preds = %if.end, %entry - %tmp = load i32, i32* %i, align 4, !dbg !15 - %inc = add nsw i32 %tmp, 1, !dbg !15 - store i32 %inc, i32* %i, align 4, !dbg !15 - %cmp = icmp slt i32 %tmp, 400000000, !dbg !15 - br i1 %cmp, label %while.body, label %while.end, !dbg !15 - -while.body: ; preds = %while.cond - %tmp1 = load i32, i32* %i, align 4, !dbg !17 - %cmp1 = icmp ne i32 %tmp1, 100, !dbg !17 - br i1 %cmp1, label %if.then, label %if.else, !dbg !17 - -if.then: ; preds = %while.body - %tmp2 = load i32, i32* %i, align 4, !dbg !19 - %tmp3 = load i32, i32* %s, align 4, !dbg !19 - %call = call i32 @_Z3sumii(i32 %tmp2, i32 %tmp3), !dbg !19 - store i32 %call, i32* %s, align 4, !dbg !19 - br label %if.end, !dbg !19 - -if.else: ; preds = %while.body - store i32 30, i32* %s, align 4, !dbg !21 - br label %if.end - -if.end: ; preds = %if.else, %if.then - br label %while.cond, !dbg !23 - -while.end: ; preds = %while.cond - %tmp4 = load i32, i32* %s, align 4, !dbg !25 - %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i32 %tmp4), !dbg !25 - ret i32 0, !dbg !26 -} - -declare i32 @printf(i8*, ...) - -attributes #0 = { "use-sample-profile" } - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!3, !4} -!llvm.ident = !{!5} - -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.5 ", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2) -!1 = !DIFile(filename: "calls.cc", directory: ".") -!2 = !{} -!3 = !{i32 2, !"Dwarf Version", i32 4} -!4 = !{i32 1, !"Debug Info Version", i32 3} -!5 = !{!"clang version 3.5 "} -!6 = distinct !DISubprogram(name: "sum", linkageName: "_Z3sumii", scope: !1, file: !1, line: 3, type: !7, scopeLine: 3, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!7 = !DISubroutineType(types: !2) -!8 = !DILocation(line: 4, scope: !6) -!9 = distinct !DISubprogram(name: "sub", linkageName: "_Z3subii", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!10 = !DILocation(line: 20, scope: !9) -!11 = !DILocation(line: 21, scope: !9) -!12 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 7, type: !7, scopeLine: 7, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!13 = !DILocation(line: 8, scope: !12) -!14 = !DILocation(line: 9, scope: !12) -!15 = !DILocation(line: 9, scope: !16) -!16 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 2) -!17 = !DILocation(line: 10, scope: !18) -!18 = distinct !DILexicalBlock(scope: !12, file: !1, line: 10) -!19 = !DILocation(line: 10, scope: !20) -!20 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 2) -!21 = !DILocation(line: 10, scope: !22) -!22 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 4) -!23 = !DILocation(line: 10, scope: !24) -!24 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 6) -!25 = !DILocation(line: 11, scope: !12) -!26 = !DILocation(line: 12, scope: !12) - - -; DEFAULT: _Z3sumii inlined into main -; DEFAULT: _Z3subii inlined into _Z3sumii -; DEFAULT-NOT: _Z3subii inlined into main - -; REPLAY: _Z3sumii inlined into main -; REPLAY: _Z3subii inlined into main -; REPLA-NOT: _Z3subii inlined into _Z3sumii From 020545d386cf70b6c6cd2fb1d1c6bf0090afe4aa Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 17 Jul 2020 15:05:42 -0700 Subject: [PATCH 681/771] Temporarily Revert "[OpenMP] Add Additional Function Attribute Information to OMPKinds.def" as it's causing a few unused variable warnings via the macro instantiation: sources/llvm-project/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def:649:17: error: unused variable 'InaccessibleOnlyAttrs' [-Werror,-Wunused-variable] __OMP_ATTRS_SET(InaccessibleOnlyAttrs, ^ This reverts commit 09fe0c5ab9ca5846d6cb625e9be47fdcfe49b93c. --- .../include/llvm/Frontend/OpenMP/OMPKinds.def | 669 +++++++--------- llvm/test/Transforms/OpenMP/add_attributes.ll | 745 ++++++------------ .../Transforms/OpenMP/parallel_deletion.ll | 2 +- 3 files changed, 520 insertions(+), 896 deletions(-) diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index bb476f6a34d4e..0dc2b34f2e4d6 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -383,8 +383,7 @@ __OMP_RTL(__kmpc_push_proc_bind, false, Void, IdentPtr, Int32, /* Int */ Int32) __OMP_RTL(__kmpc_serialized_parallel, false, Void, IdentPtr, Int32) __OMP_RTL(__kmpc_end_serialized_parallel, false, Void, IdentPtr, Int32) __OMP_RTL(__kmpc_omp_reg_task_with_affinity, false, Int32, IdentPtr, Int32, - /* kmp_task_t */ VoidPtr, Int32, - /* kmp_task_affinity_info_t */ VoidPtr) + Int8Ptr, Int32, Int8Ptr) __OMP_RTL(omp_get_thread_num, false, Int32, ) __OMP_RTL(omp_get_num_threads, false, Int32, ) @@ -431,7 +430,8 @@ __OMP_RTL(__kmpc_reduce, false, Int32, IdentPtr, Int32, Int32, SizeTy, VoidPtr, ReduceFunctionPtr, KmpCriticalNamePtrTy) __OMP_RTL(__kmpc_reduce_nowait, false, Int32, IdentPtr, Int32, Int32, SizeTy, VoidPtr, ReduceFunctionPtr, KmpCriticalNamePtrTy) -__OMP_RTL(__kmpc_end_reduce, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy) +__OMP_RTL(__kmpc_end_reduce, false, Void, IdentPtr, Int32, + KmpCriticalNamePtrTy) __OMP_RTL(__kmpc_end_reduce_nowait, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy) @@ -514,10 +514,10 @@ __OMP_RTL(__kmpc_taskloop, false, Void, IdentPtr, /* Int */ Int32, VoidPtr, /* Int */ Int32, Int64, VoidPtr) __OMP_RTL(__kmpc_omp_target_task_alloc, false, /* kmp_task_t */ VoidPtr, IdentPtr, Int32, Int32, SizeTy, SizeTy, TaskRoutineEntryPtr, Int64) -__OMP_RTL(__kmpc_taskred_modifier_init, false, /* kmp_taskgroup */ VoidPtr, - IdentPtr, /* Int */ Int32, /* Int */ Int32, /* Int */ Int32, VoidPtr) -__OMP_RTL(__kmpc_taskred_init, false, /* kmp_taskgroup */ VoidPtr, - /* Int */ Int32, /* Int */ Int32, VoidPtr) +__OMP_RTL(__kmpc_taskred_modifier_init, false, VoidPtr, IdentPtr, + /* Int */ Int32, /* Int */ Int32, /* Int */ Int32, VoidPtr) +__OMP_RTL(__kmpc_taskred_init, false, VoidPtr, /* Int */ Int32, + /* Int */ Int32, VoidPtr) __OMP_RTL(__kmpc_task_reduction_modifier_fini, false, Void, IdentPtr, /* Int */ Int32, /* Int */ Int32) __OMP_RTL(__kmpc_task_reduction_get_th_data, false, VoidPtr, Int32, VoidPtr, @@ -594,9 +594,7 @@ __OMP_RTL(__last, false, Void, ) #undef __OMP_RTL #undef OMP_RTL -#define ParamAttrs(...) ArrayRef({__VA_ARGS__}) #define EnumAttr(Kind) Attribute::get(Ctx, Attribute::AttrKind::Kind) -#define EnumAttrInt(Kind, N) Attribute::get(Ctx, Attribute::AttrKind::Kind, N) #define AttributeSet(...) \ AttributeSet::get(Ctx, ArrayRef({__VA_ARGS__})) @@ -609,88 +607,19 @@ __OMP_RTL(__last, false, Void, ) __OMP_ATTRS_SET(GetterAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(ReadOnly), - EnumAttr(NoSync), EnumAttr(NoFree), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn)) + EnumAttr(NoSync), EnumAttr(NoFree), EnumAttr(InaccessibleMemOnly)) : AttributeSet(EnumAttr(NoUnwind))) __OMP_ATTRS_SET(GetterArgWriteAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(NoFree), - EnumAttr(InaccessibleMemOrArgMemOnly), - EnumAttr(WillReturn)) + EnumAttr(NoFree), EnumAttr(InaccessibleMemOrArgMemOnly)) : AttributeSet(EnumAttr(NoUnwind))) __OMP_ATTRS_SET(SetterAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(WriteOnly), - EnumAttr(NoSync), EnumAttr(NoFree), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(DefaultAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(WillReturn), EnumAttr(NoFree)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(BarrierAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(InaccessibleArgOnlyAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(InaccessibleMemOrArgMemOnly), - EnumAttr(WillReturn), EnumAttr(NoFree)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(InaccessibleOnlyAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(InaccessibleMemOnly), - EnumAttr(WillReturn), EnumAttr(NoFree)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(AllocAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(WillReturn)) + EnumAttr(NoSync), EnumAttr(NoFree), EnumAttr(InaccessibleMemOnly)) : AttributeSet(EnumAttr(NoUnwind))) -__OMP_ATTRS_SET(ForkAttrs, OptimisticAttributes - ? AttributeSet(EnumAttr(NoUnwind)) - : AttributeSet(EnumAttr(NoUnwind))) - -__OMP_ATTRS_SET(ReadOnlyPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(ReadOnly), EnumAttr(NoFree), - EnumAttr(NoCapture)) - : AttributeSet()) - -__OMP_ATTRS_SET(WriteOnlyPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(WriteOnly), EnumAttr(NoFree), - EnumAttr(NoCapture)) - : AttributeSet()) - -__OMP_ATTRS_SET(ArgPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoCapture), EnumAttr(NoFree)) - : AttributeSet()) - -__OMP_ATTRS_SET(ReturnPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoAlias)) - : AttributeSet()) - -__OMP_ATTRS_SET(ReturnAlignedPtrAttrs, - OptimisticAttributes - ? AttributeSet(EnumAttr(NoAlias), EnumAttrInt(Alignment, 8), - EnumAttrInt(DereferenceableOrNull, 8)) - : AttributeSet()) - #undef __OMP_ATTRS_SET #undef OMP_ATTRS_SET @@ -701,309 +630,295 @@ __OMP_ATTRS_SET(ReturnAlignedPtrAttrs, #define __OMP_RTL_ATTRS(Name, FnAttrSet, RetAttrSet, ArgAttrSets) \ OMP_RTL_ATTRS(OMPRTL_##Name, FnAttrSet, RetAttrSet, ArgAttrSets) -__OMP_RTL_ATTRS(__kmpc_barrier, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_cancel, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_cancel_barrier, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_flush, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_global_thread_num, GetterAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_fork_call, ForkAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_taskwait, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_taskyield, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_push_num_threads, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_push_proc_bind, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_serialized_parallel, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_serialized_parallel, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_reg_task_with_affinity, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs, - AttributeSet(), ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(omp_get_thread_num, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_num_threads, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_max_threads, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_in_parallel, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_dynamic, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_cancellation, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_nested, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS( - omp_get_schedule, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)), - AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)))) -__OMP_RTL_ATTRS(omp_get_thread_limit, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_barrier, AttributeSet(), AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_cancel, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_cancel_barrier, AttributeSet(), AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_flush, AttributeSet(), AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_global_thread_num, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_fork_call, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_omp_taskwait, AttributeSet(), AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_omp_taskyield, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_push_num_threads, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_push_proc_bind, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_serialized_parallel, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end_serialized_parallel, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(omp_get_thread_num, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_num_threads, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_max_threads, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_in_parallel, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_dynamic, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_cancellation, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_nested, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_schedule, GetterArgWriteAttrs, AttributeSet(), + ArrayRef( + {AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)), + AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly))})) +__OMP_RTL_ATTRS(omp_get_thread_limit, GetterAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(omp_get_supported_active_levels, GetterAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_max_active_levels, GetterAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_level, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_ancestor_thread_num, GetterAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_team_size, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_active_level, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_in_final, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_proc_bind, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_num_places, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_num_procs, GetterAttrs, AttributeSet(), ParamAttrs()) + {}) +__OMP_RTL_ATTRS(omp_get_max_active_levels, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_level, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_ancestor_thread_num, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_team_size, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_active_level, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_in_final, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_proc_bind, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_num_places, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_num_procs, GetterAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(omp_get_place_proc_ids, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(AttributeSet(), AttributeSet(EnumAttr(NoCapture), - EnumAttr(WriteOnly)))) -__OMP_RTL_ATTRS(omp_get_place_num, GetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_partition_num_places, GetterAttrs, AttributeSet(), - ParamAttrs()) -__OMP_RTL_ATTRS(omp_get_partition_place_nums, GetterAttrs, AttributeSet(), - ParamAttrs()) - -__OMP_RTL_ATTRS(omp_set_num_threads, SetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_set_dynamic, SetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_set_nested, SetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_set_schedule, SetterAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(omp_set_max_active_levels, SetterAttrs, AttributeSet(), - ParamAttrs()) - -__OMP_RTL_ATTRS(__kmpc_master, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_master, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_critical, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_critical_with_hint, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_end_critical, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) - -__OMP_RTL_ATTRS(__kmpc_begin, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_reduce, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), ReadOnlyPtrAttrs, AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_reduce_nowait, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), ReadOnlyPtrAttrs, AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_end_reduce, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_end_reduce_nowait, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) - -__OMP_RTL_ATTRS(__kmpc_ordered, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_ordered, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_for_static_init_4, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_for_static_init_4u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_for_static_init_8, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_for_static_init_8u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_for_static_fini, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_4, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_4u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_8, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_8u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_4, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_4u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_8, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_8u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4u, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8u, InaccessibleArgOnlyAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_team_static_init_4, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_team_static_init_4u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_team_static_init_8, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_team_static_init_8u, GetterArgWriteAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - ArgPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8u, GetterArgWriteAttrs, - AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, - ArgPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_single, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_end_single, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_omp_task_alloc, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_task, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_end_taskgroup, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_taskgroup, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_task_begin_if0, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_task_complete_if0, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_omp_task_with_deps, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), ReadOnlyPtrAttrs, AttributeSet(), - ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_taskloop, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), ArgPtrAttrs, ArgPtrAttrs, - AttributeSet(), AttributeSet(), AttributeSet(), - AttributeSet(), AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_omp_target_task_alloc, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - AttributeSet(), AttributeSet(), ReadOnlyPtrAttrs, - AttributeSet())) -__OMP_RTL_ATTRS(__kmpc_taskred_modifier_init, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_taskred_init, DefaultAttrs, AttributeSet(), ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_fini, BarrierAttrs, - AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_task_reduction_get_th_data, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_task_reduction_init, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_init, DefaultAttrs, - ReturnPtrAttrs, ParamAttrs()) -__OMP_RTL_ATTRS(__kmpc_proxy_task_completed_ooo, DefaultAttrs, AttributeSet(), - ParamAttrs()) - -__OMP_RTL_ATTRS(__kmpc_omp_wait_deps, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_cancellationpoint, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_fork_teams, ForkAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_push_num_teams, InaccessibleArgOnlyAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_copyprivate, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), - ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_threadprivate_cached, DefaultAttrs, ReturnPtrAttrs, - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_threadprivate_register, DefaultAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs, - ReadOnlyPtrAttrs, ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_doacross_init, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_doacross_post, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_doacross_wait, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) -__OMP_RTL_ATTRS(__kmpc_doacross_fini, BarrierAttrs, AttributeSet(), - ParamAttrs(ReadOnlyPtrAttrs)) - -__OMP_RTL_ATTRS(__kmpc_alloc, DefaultAttrs, ReturnPtrAttrs, {}) -__OMP_RTL_ATTRS(__kmpc_free, AllocAttrs, AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_init_allocator, DefaultAttrs, ReturnPtrAttrs, {}) -__OMP_RTL_ATTRS(__kmpc_destroy_allocator, AllocAttrs, AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_push_target_tripcount, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_mapper, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_nowait_mapper, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_teams_mapper, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_teams_nowait_mapper, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_register_requires, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_begin_mapper, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_begin_nowait_mapper, ForkAttrs, - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_end_mapper, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_end_nowait_mapper, ForkAttrs, - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_update_mapper, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_update_nowait_mapper, ForkAttrs, - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_mapper_num_components, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_push_mapper_component, ForkAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_allow_completion_event, DefaultAttrs, - ReturnPtrAttrs, ParamAttrs(ReadOnlyPtrAttrs)) + ArrayRef({AttributeSet(), + AttributeSet(EnumAttr(NoCapture), + EnumAttr(WriteOnly))})) +__OMP_RTL_ATTRS(omp_get_place_num, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_partition_num_places, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_get_partition_place_nums, GetterAttrs, AttributeSet(), {}) + +__OMP_RTL_ATTRS(omp_set_num_threads, SetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_set_dynamic, SetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_set_nested, SetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_set_schedule, SetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(omp_set_max_active_levels, SetterAttrs, AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_master, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end_master, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_critical, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_critical_with_hint, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end_critical, + AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_begin, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_reduce, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_reduce_nowait, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end_reduce, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end_reduce_nowait, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_ordered, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end_ordered, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_for_static_init_4, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_for_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_for_static_init_8, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_for_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_for_static_fini, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_4, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_4u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_8, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_8u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_4, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_4u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_8, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_8u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_team_static_init_4, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_team_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_team_static_init_8, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_team_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_single, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end_single, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_omp_task_alloc, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_omp_task, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_end_taskgroup, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_taskgroup, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_omp_task_begin_if0, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_omp_task_complete_if0, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_omp_task_with_deps, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_taskloop, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_omp_target_task_alloc, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_taskred_modifier_init, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_taskred_init, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_fini, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_task_reduction_get_th_data, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_task_reduction_init, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_init, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_proxy_task_completed_ooo, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_omp_wait_deps, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_cancellationpoint, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_fork_teams, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_push_num_teams, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_copyprivate, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_threadprivate_cached, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_threadprivate_register, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_doacross_init, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_doacross_post, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_doacross_wait, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_doacross_fini, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_alloc, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_free, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_init_allocator, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_destroy_allocator, AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_push_target_tripcount, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_nowait_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_teams_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_teams_nowait_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_register_requires, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_begin_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_begin_nowait_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_end_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_end_nowait_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_update_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_update_nowait_mapper, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_mapper_num_components, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_push_mapper_component, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_task_allow_completion_event, + AttributeSet(EnumAttr(NoUnwind)), + AttributeSet(), {}) #undef __OMP_RTL_ATTRS #undef OMP_RTL_ATTRS #undef AttributeSet #undef EnumAttr -#undef EnumAttrInt -#undef ParamAttrs ///} diff --git a/llvm/test/Transforms/OpenMP/add_attributes.ll b/llvm/test/Transforms/OpenMP/add_attributes.ll index e92447d79feac..6e10613ed43c3 100644 --- a/llvm/test/Transforms/OpenMP/add_attributes.ll +++ b/llvm/test/Transforms/OpenMP/add_attributes.ll @@ -890,373 +890,373 @@ declare void @__kmpc_proxy_task_completed_ooo(i8*) ; CHECK: ; Function Attrs: nounwind ; CHECK-NEXT: declare dso_local i32 @omp_get_supported_active_levels() #0 -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_barrier(%struct.ident_t*, i32) #0 +; CHECK-NOT: Function Attrs +; CHECK: declare void @__kmpc_barrier(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_cancel_barrier(%struct.ident_t*, i32) #0 +; CHECK-NOT: Function Attrs +; CHECK: declare i32 @__kmpc_cancel_barrier(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_flush(%struct.ident_t*) #0 +; CHECK-NOT: Function Attrs +; CHECK: declare void @__kmpc_flush(%struct.ident_t*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_omp_taskwait(%struct.ident_t*, i32) #0 +; CHECK-NOT: Function Attrs +; CHECK: declare i32 @__kmpc_omp_taskwait(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t*, i32, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t*, i32, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t*, i32, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_master(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare i32 @__kmpc_master(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_master(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare void @__kmpc_end_master(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_critical(%struct.ident_t*, i32, [8 x i32]*) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare void @__kmpc_critical(%struct.ident_t*, i32, [8 x i32]*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t*, i32, [8 x i32]*, i32) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t*, i32, [8 x i32]*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_critical(%struct.ident_t*, i32, [8 x i32]*) #0 +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly +; CHECK-NEXT: declare void @__kmpc_end_critical(%struct.ident_t*, i32, [8 x i32]*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_begin(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_begin(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end(%struct.ident_t*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end(%struct.ident_t*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t*, i32, [8 x i32]*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t*, i32, [8 x i32]*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t*, i32, [8 x i32]*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t*, i32, [8 x i32]*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_ordered(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_ordered(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_single(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_single(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_single(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_single(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_omp_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_omp_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t*, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t*, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t*, i32, i32, i32, i32, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t*, i32, i32, i32, i32, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t*, i32, i32, i32, i32, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t*, i32, i32, i32, i32, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t*, i32, i32, i64, i64, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t*, i32, i32, i64, i64, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t*, i32, i32, i64, i64, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t*, i32, i32, i64, i64, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t*, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t*, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t*, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t*, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t*, i32, i8*, i32, i8*, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t*, i32, i8*, i32, i8*, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t*, i32, i32, i8*, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t*, i32, i32, i8*, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t*, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t*, i32, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t*, i32, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_taskloop(%struct.ident_t*, i32, i8*, i32, i64*, i64*, i64, i32, i32, i64, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_taskloop(%struct.ident_t*, i32, i8*, i32, i64*, i64*, i64, i32, i32, i64, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_omp_target_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_omp_target_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_taskred_modifier_init(%struct.ident_t*, i32, i32, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_taskred_modifier_init(%struct.ident_t*, i32, i32, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t*, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t*, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t*, i32, i64, i8*, void (i8*, i8*)*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t*, i32, i64, i8*, void (i8*, i8*)*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_threadprivate_cached(%struct.ident_t*, i32, i8*, i64, i8***) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_threadprivate_cached(%struct.ident_t*, i32, i8*, i64, i8***) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t*, i8*, i8* (i8*)*, i8* (i8*, i8*)*, void (i8*)*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t*, i8*, i8* (i8*)*, i8* (i8*, i8*)*, void (i8*)*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t*, i32, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t*, i32, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t*, i32, i64*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t*, i32, i64*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t*, i32, i64*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t*, i32, i64*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t*, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t*, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_alloc(i32, i64, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_alloc(i32, i64, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_free(i32, i8*, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_free(i32, i8*, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_register_requires(i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_register_requires(i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i64 @__tgt_mapper_num_components(i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i64 @__tgt_mapper_num_components(i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_allow_completion_event(%struct.ident_t*, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_allow_completion_event(%struct.ident_t*, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_init(i32, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_init(i32, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) -; CHECK: ; Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) #0 +; CHECK: Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_num_threads(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_dynamic(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_nested(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_max_active_levels(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_schedule(i32, i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_num_threads() #1 ; OPTIMISTIC-NOT: Function Attrs ; OPTIMISTIC: declare dso_local void @use_int(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_dynamic() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_nested() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_max_threads() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_thread_num() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_num_procs() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_in_parallel() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_in_final() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_active_level() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_level() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_ancestor_thread_num(i32) #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_team_size(i32) #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_thread_limit() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_max_active_levels() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind ; OPTIMISTIC-NEXT: declare dso_local void @omp_get_schedule(i32* nocapture writeonly, i32* nocapture writeonly) #2 ; OPTIMISTIC-NOT: Function Attrs @@ -1418,299 +1418,8 @@ declare void @__kmpc_proxy_task_completed_ooo(i8*) ; OPTIMISTIC-NOT: Function Attrs ; OPTIMISTIC: declare dso_local i32 @omp_pause_resource_all(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_supported_active_levels() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t* nocapture nofree readonly) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_fork_call(%struct.ident_t* nocapture nofree readonly, i32, void (i32*, i32*, ...)* nocapture nofree readonly, ...) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_taskwait(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t* nocapture nofree readonly, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t* nocapture nofree readonly, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t* nocapture nofree readonly, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_master(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_end_master(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_critical(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*, i32) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_end_critical(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_begin(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_end(%struct.ident_t* nocapture nofree readonly) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, [8 x i32]*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, [8 x i32]*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_ordered(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i32 @__kmpc_single(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_end_single(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_omp_task_alloc(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i32 (i32, i8*)* nocapture nofree readonly) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t* nocapture nofree readonly, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32, i32, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32, i32, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64, i64, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64, i64, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i32, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i32, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i64, i64) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t* nocapture nofree readonly, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t* nocapture nofree readonly, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t* nocapture nofree readonly, i32, i8*, i32, i8* nocapture nofree readonly, i32, i8* nocapture nofree readonly) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t* nocapture nofree readonly, i32, i32, i8* nocapture nofree readonly, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t* nocapture nofree readonly, i32, i32) - -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t* nocapture nofree readonly, i32, i32, i32) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t* nocapture nofree readonly, i32, void (i32*, i32*, ...)* nocapture nofree readonly, ...) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_taskloop(%struct.ident_t* nocapture nofree readonly, i32, i8*, i32, i64* nocapture nofree, i64* nocapture nofree, i64, i32, i32, i64, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_omp_target_task_alloc(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i32 (i32, i8*)* nocapture nofree readonly, i64) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_taskred_modifier_init(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t* nocapture nofree readonly, i32, i32) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t* nocapture nofree readonly, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, i32) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_threadprivate_cached(%struct.ident_t* nocapture nofree readonly, i32, i8*, i64, i8***) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t* nocapture nofree readonly, i8*, i8* (i8*)* nocapture nofree readonly, i8* (i8*, i8*)* nocapture nofree readonly, void (i8*)* nocapture nofree readonly) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t* nocapture nofree readonly, i32, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t* nocapture nofree readonly, i32, i64* nocapture nofree readonly) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t* nocapture nofree readonly, i32, i64* nocapture nofree readonly) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t* nocapture nofree readonly, i32) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_alloc(i32, i64, i8*) - -; OPTIMISTIC: ; Function Attrs: nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_free(i32, i8*, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) - -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly -; OPTIMISTIC-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__tgt_register_requires(i64) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare i64 @__tgt_mapper_num_components(i8*) - -; OPTIMISTIC: ; Function Attrs: nounwind -; OPTIMISTIC-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_allow_completion_event(%struct.ident_t* nocapture nofree readonly, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_init(i32, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) - -; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn -; OPTIMISTIC-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) diff --git a/llvm/test/Transforms/OpenMP/parallel_deletion.ll b/llvm/test/Transforms/OpenMP/parallel_deletion.ll index 07976660546f8..4d2f8e7cbc5e8 100644 --- a/llvm/test/Transforms/OpenMP/parallel_deletion.ll +++ b/llvm/test/Transforms/OpenMP/parallel_deletion.ll @@ -393,7 +393,7 @@ entry: define internal void @.omp.reduction.reduction_func(i8* %arg, i8* %arg1) { ; CHECK-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func -; CHECK-SAME: (i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #{{[0-9]+}} +; CHECK-SAME: (i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #10 ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP:%.*]] = bitcast i8* [[ARG1]] to i32** ; CHECK-NEXT: [[TMP2:%.*]] = load i32*, i32** [[TMP]], align 8 From 7fcc1bb4b654461c3109b01e1fe7eae191a86f7f Mon Sep 17 00:00:00 2001 From: Michael Spencer Date: Fri, 17 Jul 2020 16:12:18 -0600 Subject: [PATCH 682/771] [clangd] Fix the build with clang <3.9. In clang <3.9 the `unique_ptr` constructor that is supposed to allow for Derived to Base conversion does not work. Remove this if we drop support for such configurations. This is the same fix as in fda901a987ddd, and it updates the comments to better reflect the actual issue. The same thing reproduces with libc++ with older clangs. --- clang-tools-extra/clangd/ConfigProvider.cpp | 6 +++++- llvm/utils/TableGen/OptParserEmitter.cpp | 16 ++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clangd/ConfigProvider.cpp b/clang-tools-extra/clangd/ConfigProvider.cpp index eec1ae9921947..a56cdd755322a 100644 --- a/clang-tools-extra/clangd/ConfigProvider.cpp +++ b/clang-tools-extra/clangd/ConfigProvider.cpp @@ -209,7 +209,11 @@ Provider::combine(std::vector Providers) { }; auto Result = std::make_unique(); Result->Providers = std::move(Providers); - return Result; + // FIXME: This is a workaround for a bug in older versions of clang (< 3.9) + // The constructor that is supposed to allow for Derived to Base + // conversion does not work. Remove this if we drop support for such + // configurations. + return std::unique_ptr(Result.release()); } Config Provider::getConfig(const Params &P, DiagnosticCallback DC) const { diff --git a/llvm/utils/TableGen/OptParserEmitter.cpp b/llvm/utils/TableGen/OptParserEmitter.cpp index 34699b55e274b..6e49e248e4b81 100644 --- a/llvm/utils/TableGen/OptParserEmitter.cpp +++ b/llvm/utils/TableGen/OptParserEmitter.cpp @@ -110,10 +110,10 @@ class MarshallingFlagInfo final : public MarshallingKindInfo { static std::unique_ptr create(const Record &R) { std::unique_ptr Ret(new MarshallingFlagInfo(R)); Ret->IsPositive = R.getValueAsBit("IsPositive"); - // FIXME: This is a workaround for a bug in older versions of libstdc++ when - // compiled with Clang. The constructor that is supposed to allow for - // Derived to Base conversion does not work. Remove this if we drop - // support for such configurations. + // FIXME: This is a workaround for a bug in older versions of clang (< 3.9) + // The constructor that is supposed to allow for Derived to Base + // conversion does not work. Remove this if we drop support for such + // configurations. return std::unique_ptr(Ret.release()); } @@ -208,10 +208,10 @@ struct SimpleEnumValueTable { "values"); } - // FIXME: This is a workaround for a bug in older versions of libstdc++ when - // compiled with Clang. The constructor that is supposed to allow for - // Derived to Base conversion does not work. Remove this if we drop - // support for such configurations. + // FIXME: This is a workaround for a bug in older versions of clang (< 3.9) + // The constructor that is supposed to allow for Derived to Base + // conversion does not work. Remove this if we drop support for such + // configurations. return std::unique_ptr(Ret.release()); } From 86fb2db49b33aa4759d351b30ea1f6ebbe252c60 Mon Sep 17 00:00:00 2001 From: AndreyChurbanov Date: Sat, 18 Jul 2020 01:15:37 +0300 Subject: [PATCH 683/771] [OpenMP] libomp cleanup: check presence of hwloc objects CORE, PACKAGE hwloc documentation guarantees the only object that is always present in the topology is PU. We can check the presence of other objects in the topology, just in case. Differential Revision: https://reviews.llvm.org/D84065 --- openmp/runtime/src/kmp_affinity.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/openmp/runtime/src/kmp_affinity.cpp b/openmp/runtime/src/kmp_affinity.cpp index 47e70477ced6c..f78288710349a 100644 --- a/openmp/runtime/src/kmp_affinity.cpp +++ b/openmp/runtime/src/kmp_affinity.cpp @@ -577,11 +577,17 @@ static int __kmp_affinity_create_hwloc_map(AddrUnsPair **address2os, // Hack to try and infer the machine topology using only the data // available from cpuid on the current thread, and __kmp_xproc. KMP_ASSERT(__kmp_affinity_type == affinity_none); - - nCoresPerPkg = __kmp_hwloc_get_nobjs_under_obj( - hwloc_get_obj_by_type(tp, HWLOC_OBJ_PACKAGE, 0), HWLOC_OBJ_CORE); - __kmp_nThreadsPerCore = __kmp_hwloc_get_nobjs_under_obj( - hwloc_get_obj_by_type(tp, HWLOC_OBJ_CORE, 0), HWLOC_OBJ_PU); + // hwloc only guarantees existance of PU object, so check PACKAGE and CORE + hwloc_obj_t o = hwloc_get_obj_by_type(tp, HWLOC_OBJ_PACKAGE, 0); + if (o != NULL) + nCoresPerPkg = __kmp_hwloc_get_nobjs_under_obj(o, HWLOC_OBJ_CORE); + else + nCoresPerPkg = 1; // no PACKAGE found + o = hwloc_get_obj_by_type(tp, HWLOC_OBJ_CORE, 0); + if (o != NULL) + __kmp_nThreadsPerCore = __kmp_hwloc_get_nobjs_under_obj(o, HWLOC_OBJ_PU); + else + __kmp_nThreadsPerCore = 1; // no CORE found __kmp_ncores = __kmp_xproc / __kmp_nThreadsPerCore; nPackages = (__kmp_xproc + nCoresPerPkg - 1) / nCoresPerPkg; if (__kmp_affinity_verbose) { From cf2274b779f5ffee476cfe40994e6963a51c6428 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 17 Jul 2020 11:21:08 -0700 Subject: [PATCH 684/771] [flang] Allow ! and // comments after some preprocessing directives Old-style C /*comments*/ are omitted from preprocessor directive token sequences by the prescanner, but line-ending C++ and Fortran free-form comments are not since their handling might depend on the directive. Add code to skip these line-ending comments as appropriate in place of existing code that just skipped blanks. Reviewed By: sscalpone Differential Revision: https://reviews.llvm.org/D84061 --- flang/lib/Parser/preprocessor.cpp | 16 +++++++--------- flang/lib/Parser/token-sequence.cpp | 25 +++++++++++++++++++++++++ flang/lib/Parser/token-sequence.h | 4 ++++ flang/test/Parser/pp-dir-comments.f90 | 19 +++++++++++++++++++ 4 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 flang/test/Parser/pp-dir-comments.f90 diff --git a/flang/lib/Parser/preprocessor.cpp b/flang/lib/Parser/preprocessor.cpp index 3b09597ddeb75..a1f07967d9b08 100644 --- a/flang/lib/Parser/preprocessor.cpp +++ b/flang/lib/Parser/preprocessor.cpp @@ -453,10 +453,9 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) { dir.GetIntervalProvenanceRange(dirOffset, tokens - dirOffset), "# missing or invalid name"_err_en_US); } else { - j = dir.SkipBlanks(j + 1); - if (j != tokens) { + if (dir.IsAnythingLeft(++j)) { prescanner->Say(dir.GetIntervalProvenanceRange(j, tokens - j), - "#undef: excess tokens at end of directive"_err_en_US); + "#undef: excess tokens at end of directive"_en_US); } else { definitions_.erase(nameToken); } @@ -468,8 +467,7 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) { dir.GetIntervalProvenanceRange(dirOffset, tokens - dirOffset), "#%s: missing name"_err_en_US, dirName); } else { - j = dir.SkipBlanks(j + 1); - if (j != tokens) { + if (dir.IsAnythingLeft(++j)) { prescanner->Say(dir.GetIntervalProvenanceRange(j, tokens - j), "#%s: excess tokens at end of directive"_en_US, dirName); } @@ -489,9 +487,9 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) { dir.GetTokenProvenanceRange(dirOffset)); } } else if (dirName == "else") { - if (j != tokens) { + if (dir.IsAnythingLeft(j)) { prescanner->Say(dir.GetIntervalProvenanceRange(j, tokens - j), - "#else: excess tokens at end of directive"_err_en_US); + "#else: excess tokens at end of directive"_en_US); } else if (ifStack_.empty()) { prescanner->Say(dir.GetTokenProvenanceRange(dirOffset), "#else: not nested within #if, #ifdef, or #ifndef"_err_en_US); @@ -516,9 +514,9 @@ void Preprocessor::Directive(const TokenSequence &dir, Prescanner *prescanner) { dir.GetTokenProvenanceRange(dirOffset)); } } else if (dirName == "endif") { - if (j != tokens) { + if (dir.IsAnythingLeft(j)) { prescanner->Say(dir.GetIntervalProvenanceRange(j, tokens - j), - "#endif: excess tokens at end of directive"_err_en_US); + "#endif: excess tokens at end of directive"_en_US); } else if (ifStack_.empty()) { prescanner->Say(dir.GetTokenProvenanceRange(dirOffset), "#endif: no #if, #ifdef, or #ifndef"_err_en_US); diff --git a/flang/lib/Parser/token-sequence.cpp b/flang/lib/Parser/token-sequence.cpp index ce94f26235013..07c5b12e5f759 100644 --- a/flang/lib/Parser/token-sequence.cpp +++ b/flang/lib/Parser/token-sequence.cpp @@ -56,6 +56,31 @@ std::size_t TokenSequence::SkipBlanks(std::size_t at) const { return tokens; // even if at > tokens } +// C-style /*comments*/ are removed from preprocessing directive +// token sequences by the prescanner, but not C++ or Fortran +// free-form line-ending comments (//... and !...) because +// ignoring them is directive-specific. +bool TokenSequence::IsAnythingLeft(std::size_t at) const { + std::size_t tokens{start_.size()}; + for (; at < tokens; ++at) { + auto tok{TokenAt(at)}; + const char *end{tok.end()}; + for (const char *p{tok.begin()}; p < end; ++p) { + switch (*p) { + case '/': + return p + 1 >= end || p[1] != '/'; + case '!': + return false; + case ' ': + break; + default: + return true; + } + } + } + return false; +} + void TokenSequence::RemoveLastToken() { CHECK(!start_.empty()); CHECK(nextStart_ > start_.back()); diff --git a/flang/lib/Parser/token-sequence.h b/flang/lib/Parser/token-sequence.h index d73b3c20be6f4..d98c0b955c5e9 100644 --- a/flang/lib/Parser/token-sequence.h +++ b/flang/lib/Parser/token-sequence.h @@ -71,6 +71,10 @@ class TokenSequence { std::size_t SkipBlanks(std::size_t) const; + // True if anything remains in the sequence at & after the given offset + // except blanks and line-ending C++ and Fortran free-form comments. + bool IsAnythingLeft(std::size_t) const; + void PutNextTokenChar(char ch, Provenance provenance) { char_.emplace_back(ch); provenances_.Put({provenance, 1}); diff --git a/flang/test/Parser/pp-dir-comments.f90 b/flang/test/Parser/pp-dir-comments.f90 new file mode 100644 index 0000000000000..f5fe4ca5c71e8 --- /dev/null +++ b/flang/test/Parser/pp-dir-comments.f90 @@ -0,0 +1,19 @@ +! RUN: %f18 -funparse %s 2>&1 | FileCheck %s + +#define pmk +#ifdef pmk // comment +! CHECK: t1 +real t1 +#endif // comment +#undef pmk ! comment +#ifndef pmk ! comment +! CHECK: t2 +real t2 +#endif // comment +#if 0 /* C comment */ + 0 +! CHECK-NOT: misinterpreted +# error misinterpreted #if +#else // comment +! CHECK: END PROGRAM +end +#endif ! comment From cf5df40c4cf1a53a02ab1d56a488642e3dda8f6d Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Fri, 17 Jul 2020 15:29:50 -0700 Subject: [PATCH 685/771] Revert "[AddressSanitizer] Don't use weak linkage for __{start,stop}_asan_globals" This reverts commit d76e62fdb7a93d9a33f642b6b528f2562cc3c3f4. Reverting since this can lead to linker errors: ``` ld.lld: error: undefined hidden symbol: __start_asan_globals ``` when using --gc-sections. The linker can discard __start_asan_globals once there are no more `asan_globals` sections left, which can lead to this error if we have external linkages to them. --- .../Instrumentation/AddressSanitizer.cpp | 38 ++++++------------- .../AddressSanitizer/global_metadata.ll | 4 -- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index ee09a4d9db7e1..7516a64c6a354 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -2103,23 +2103,10 @@ void ModuleAddressSanitizer::InstrumentGlobalsELF( SetComdatForGlobalMetadata(G, Metadata, UniqueModuleId); } - // This should never be called when there are no globals, by the logic that - // computes the UniqueModuleId string, which is "" when there are no globals. - // It's important that this path is only used when there are actually some - // globals, because that means that there will certainly be a live - // `asan_globals` input section at link time and thus `__start_asan_globals` - // and `__stop_asan_globals` symbols will definitely be defined at link time. - // This means there's no need for the references to them to be weak, which - // enables better code generation because ExternalWeakLinkage implies - // isInterposable() and thus requires GOT indirection for PIC. Since these - // are known-defined hidden/dso_local symbols, direct PIC accesses without - // dynamic relocation are always sufficient. - assert(!MetadataGlobals.empty()); - assert(!UniqueModuleId.empty()); - // Update llvm.compiler.used, adding the new metadata globals. This is // needed so that during LTO these variables stay alive. - appendToCompilerUsed(M, MetadataGlobals); + if (!MetadataGlobals.empty()) + appendToCompilerUsed(M, MetadataGlobals); // RegisteredFlag serves two purposes. First, we can pass it to dladdr() // to look up the loaded image that contains it. Second, we can store in it @@ -2132,18 +2119,15 @@ void ModuleAddressSanitizer::InstrumentGlobalsELF( ConstantInt::get(IntptrTy, 0), kAsanGlobalsRegisteredFlagName); RegisteredFlag->setVisibility(GlobalVariable::HiddenVisibility); - // Create start and stop symbols. These are known to be defined by - // the linker, see comment above. - auto MakeStartStopGV = [&](const char *Prefix) { - GlobalVariable *StartStop = - new GlobalVariable(M, IntptrTy, false, GlobalVariable::ExternalLinkage, - nullptr, Prefix + getGlobalMetadataSection()); - StartStop->setVisibility(GlobalVariable::HiddenVisibility); - assert(StartStop->isImplicitDSOLocal()); - return StartStop; - }; - GlobalVariable *StartELFMetadata = MakeStartStopGV("__start_"); - GlobalVariable *StopELFMetadata = MakeStartStopGV("__stop_"); + // Create start and stop symbols. + GlobalVariable *StartELFMetadata = new GlobalVariable( + M, IntptrTy, false, GlobalVariable::ExternalWeakLinkage, nullptr, + "__start_" + getGlobalMetadataSection()); + StartELFMetadata->setVisibility(GlobalVariable::HiddenVisibility); + GlobalVariable *StopELFMetadata = new GlobalVariable( + M, IntptrTy, false, GlobalVariable::ExternalWeakLinkage, nullptr, + "__stop_" + getGlobalMetadataSection()); + StopELFMetadata->setVisibility(GlobalVariable::HiddenVisibility); // Create a call to register the globals with the runtime. IRB.CreateCall(AsanRegisterElfGlobals, diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll index 4a6f426443769..ea9f2cf3f1a9d 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll @@ -28,10 +28,6 @@ target triple = "x86_64-unknown-linux-gnu" ; during LTO. ; CHECK: @llvm.compiler.used {{.*}} @__asan_global_global {{.*}} section "llvm.metadata" -; Check that start and stop symbols will be accessed as dso_local. -; CHECK: @__start_asan_globals = external hidden global i64 -; CHECK: @__stop_asan_globals = external hidden global i64 - ; Check that location descriptors and global names were passed into __asan_register_globals: ; CHECK: call void @__asan_register_elf_globals(i64 ptrtoint (i64* @___asan_globals_registered to i64), i64 ptrtoint (i64* @__start_asan_globals to i64), i64 ptrtoint (i64* @__stop_asan_globals to i64)) From 63c081e73d3d6d75ab6c6eefa37a69d73f46ed0f Mon Sep 17 00:00:00 2001 From: Aditya Nandakumar Date: Fri, 17 Jul 2020 16:03:20 -0700 Subject: [PATCH 686/771] [GISel: Add support for CSEing SrcOps which are immediates https://reviews.llvm.org/D84072 Add G_EXTRACT to CSEConfigFull and add unit test as well. --- llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp | 1 + llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp | 3 +++ llvm/unittests/CodeGen/GlobalISel/CSETest.cpp | 9 +++++++++ 3 files changed, 13 insertions(+) diff --git a/llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp b/llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp index c4d8777615d27..071cc5b737358 100644 --- a/llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CSEInfo.cpp @@ -59,6 +59,7 @@ bool CSEConfigFull::shouldCSEOpc(unsigned Opc) { case TargetOpcode::G_UNMERGE_VALUES: case TargetOpcode::G_TRUNC: case TargetOpcode::G_PTR_ADD: + case TargetOpcode::G_EXTRACT: return true; } return false; diff --git a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp index 88173dc4d302c..6f8fd309e1b58 100644 --- a/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CSEMIRBuilder.cpp @@ -70,6 +70,9 @@ void CSEMIRBuilder::profileDstOp(const DstOp &Op, void CSEMIRBuilder::profileSrcOp(const SrcOp &Op, GISelInstProfileBuilder &B) const { switch (Op.getSrcOpKind()) { + case SrcOp::SrcType::Ty_Imm: + B.addNodeIDImmediate(static_cast(Op.getImm())); + break; case SrcOp::SrcType::Ty_Predicate: B.addNodeIDImmediate(static_cast(Op.getPredicate())); break; diff --git a/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp b/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp index 556f4f29b992e..69c21d6afb009 100644 --- a/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp +++ b/llvm/unittests/CodeGen/GlobalISel/CSETest.cpp @@ -96,6 +96,15 @@ TEST_F(AArch64GISelMITest, TestCSE) { auto CSEFMul = CSEB.buildInstr(TargetOpcode::G_AND, {s32}, {Copies[0], Copies[1]}); EXPECT_EQ(&*CSEFMul, &*NonCSEFMul); + + auto ExtractMIB = CSEB.buildInstr(TargetOpcode::G_EXTRACT, {s16}, + {Copies[0], static_cast(0)}); + auto ExtractMIB1 = CSEB.buildInstr(TargetOpcode::G_EXTRACT, {s16}, + {Copies[0], static_cast(0)}); + auto ExtractMIB2 = CSEB.buildInstr(TargetOpcode::G_EXTRACT, {s16}, + {Copies[0], static_cast(1)}); + EXPECT_EQ(&*ExtractMIB, &*ExtractMIB1); + EXPECT_NE(&*ExtractMIB, &*ExtractMIB2); } TEST_F(AArch64GISelMITest, TestCSEConstantConfig) { From 53880b8cb9c61e81457d13c0adefe51ff41664fa Mon Sep 17 00:00:00 2001 From: Michele Scandale Date: Fri, 17 Jul 2020 16:43:05 -0700 Subject: [PATCH 687/771] [CMake] Make `intrinsics_gen` dependency unconditional. The `intrinsics_gen` target exists in the CMake exports since r309389 (see LLVMConfig.cmake.in), hence projects can depend on `intrinsics_gen` even it they are built separately from LLVM. Reviewed By: MaskRay, JDevlieghere Differential Revision: https://reviews.llvm.org/D83454 --- clang/CMakeLists.txt | 2 +- clang/lib/CodeGen/CMakeLists.txt | 11 +---------- clang/lib/Frontend/CMakeLists.txt | 7 +------ clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt | 8 +------- clang/tools/clang-import-test/CMakeLists.txt | 6 +----- clang/tools/clang-offload-bundler/CMakeLists.txt | 6 +----- clang/tools/clang-offload-wrapper/CMakeLists.txt | 6 +----- clang/tools/driver/CMakeLists.txt | 6 +----- lld/COFF/CMakeLists.txt | 6 +----- lld/Common/CMakeLists.txt | 6 +----- lld/ELF/CMakeLists.txt | 6 +----- lld/MinGW/CMakeLists.txt | 6 +----- lld/lib/Core/CMakeLists.txt | 6 +----- lld/wasm/CMakeLists.txt | 6 +----- lldb/CMakeLists.txt | 2 +- lldb/source/Expression/CMakeLists.txt | 6 +----- .../Plugins/ExpressionParser/Clang/CMakeLists.txt | 6 +----- .../RenderScript/RenderScriptRuntime/CMakeLists.txt | 7 +------ 18 files changed, 18 insertions(+), 91 deletions(-) diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 7f8e0718c2ebc..948452661a32f 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -531,7 +531,7 @@ list(APPEND LLVM_COMMON_DEPENDS clang-tablegen-targets) # Force target to be built as soon as possible. Clang modules builds depend # header-wise on it as they ship all headers from the umbrella folders. Building # an entire module might include header, which depends on intrinsics_gen. -if(LLVM_ENABLE_MODULES AND NOT CLANG_BUILT_STANDALONE) +if(LLVM_ENABLE_MODULES) list(APPEND LLVM_COMMON_DEPENDS intrinsics_gen) endif() diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index c4bedf34921cc..8afd7219fbe1e 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -26,15 +26,6 @@ set(LLVM_LINK_COMPONENTS TransformUtils ) -# In a standard Clang+LLVM build, we need to generate intrinsics before -# building codegen. In a standalone build, LLVM is already built and we don't -# need this dependency. Furthermore, LLVM doesn't export it so we can't have -# this dependency. -set(codegen_deps intrinsics_gen) -if (CLANG_BUILT_STANDALONE) - set(codegen_deps) -endif() - if (MSVC) set_source_files_properties(CodeGenModule.cpp PROPERTIES COMPILE_FLAGS /bigobj) endif() @@ -99,7 +90,7 @@ add_clang_library(clangCodeGen VarBypassDetector.cpp DEPENDS - ${codegen_deps} + intrinsics_gen LINK_LIBS clangAnalysis diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index 0e23b92e2dea9..af5446618b036 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -8,11 +8,6 @@ set(LLVM_LINK_COMPONENTS Support ) -set(optional_deps intrinsics_gen) -if (CLANG_BUILT_STANDALONE) - set(optional_deps) -endif() - add_clang_library(clangFrontend ASTConsumers.cpp ASTMerge.cpp @@ -49,7 +44,7 @@ add_clang_library(clangFrontend DEPENDS ClangDriverOptions - ${optional_deps} + intrinsics_gen LINK_LIBS clangAST diff --git a/clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt b/clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt index 47f9fdf68f409..9ceb1d3318283 100644 --- a/clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt +++ b/clang/tools/clang-fuzzer/handle-llvm/CMakeLists.txt @@ -16,15 +16,9 @@ set(LLVM_LINK_COMPONENTS native ) -# Depend on LLVM IR intrinsic generation. -set(handle_llvm_deps intrinsics_gen) -if (CLANG_BUILT_STANDALONE) - set(handle_llvm_deps) -endif() - add_clang_library(clangHandleLLVM handle_llvm.cpp DEPENDS - ${handle_llvm_deps} + intrinsics_gen ) diff --git a/clang/tools/clang-import-test/CMakeLists.txt b/clang/tools/clang-import-test/CMakeLists.txt index 4ccc2d752aac4..e459de8f635f5 100644 --- a/clang/tools/clang-import-test/CMakeLists.txt +++ b/clang/tools/clang-import-test/CMakeLists.txt @@ -3,14 +3,10 @@ set(LLVM_LINK_COMPONENTS Support ) -if(NOT CLANG_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_clang_executable(clang-import-test clang-import-test.cpp DEPENDS - ${tablegen_deps} + intrinsics_gen ) set(CLANG_IMPORT_TEST_LIB_DEPS diff --git a/clang/tools/clang-offload-bundler/CMakeLists.txt b/clang/tools/clang-offload-bundler/CMakeLists.txt index 4ef099493364a..2738bf02e729f 100644 --- a/clang/tools/clang-offload-bundler/CMakeLists.txt +++ b/clang/tools/clang-offload-bundler/CMakeLists.txt @@ -1,14 +1,10 @@ set(LLVM_LINK_COMPONENTS Object Support) -if(NOT CLANG_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_clang_tool(clang-offload-bundler ClangOffloadBundler.cpp DEPENDS - ${tablegen_deps} + intrinsics_gen ) set(CLANG_OFFLOAD_BUNDLER_LIB_DEPS diff --git a/clang/tools/clang-offload-wrapper/CMakeLists.txt b/clang/tools/clang-offload-wrapper/CMakeLists.txt index 6f8940f88eabd..8bcb46267a37c 100644 --- a/clang/tools/clang-offload-wrapper/CMakeLists.txt +++ b/clang/tools/clang-offload-wrapper/CMakeLists.txt @@ -1,14 +1,10 @@ set(LLVM_LINK_COMPONENTS BitWriter Core Support TransformUtils) -if(NOT CLANG_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_clang_tool(clang-offload-wrapper ClangOffloadWrapper.cpp DEPENDS - ${tablegen_deps} + intrinsics_gen ) set(CLANG_OFFLOAD_WRAPPER_LIB_DEPS diff --git a/clang/tools/driver/CMakeLists.txt b/clang/tools/driver/CMakeLists.txt index c53485ef19576..01efebdcb929c 100644 --- a/clang/tools/driver/CMakeLists.txt +++ b/clang/tools/driver/CMakeLists.txt @@ -24,10 +24,6 @@ if(CLANG_PLUGIN_SUPPORT) set(support_plugins SUPPORT_PLUGINS) endif() -if(NOT CLANG_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_clang_tool(clang driver.cpp cc1_main.cpp @@ -35,7 +31,7 @@ add_clang_tool(clang cc1gen_reproducer_main.cpp DEPENDS - ${tablegen_deps} + intrinsics_gen ${support_plugins} ) diff --git a/lld/COFF/CMakeLists.txt b/lld/COFF/CMakeLists.txt index 4592ace373efa..796f7a82a3de1 100644 --- a/lld/COFF/CMakeLists.txt +++ b/lld/COFF/CMakeLists.txt @@ -2,10 +2,6 @@ set(LLVM_TARGET_DEFINITIONS Options.td) tablegen(LLVM Options.inc -gen-opt-parser-defs) add_public_tablegen_target(COFFOptionsTableGen) -if(NOT LLD_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_lld_library(lldCOFF Chunks.cpp DebugTypes.cpp @@ -48,5 +44,5 @@ add_lld_library(lldCOFF DEPENDS COFFOptionsTableGen - ${tablegen_deps} + intrinsics_gen ) diff --git a/lld/Common/CMakeLists.txt b/lld/Common/CMakeLists.txt index 53649032bd987..212328b784c5b 100644 --- a/lld/Common/CMakeLists.txt +++ b/lld/Common/CMakeLists.txt @@ -1,7 +1,3 @@ -if(NOT LLD_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - find_first_existing_vc_file("${LLVM_MAIN_SRC_DIR}" llvm_vc) find_first_existing_vc_file("${LLD_SOURCE_DIR}" lld_vc) @@ -57,5 +53,5 @@ add_lld_library(lldCommon ${LLVM_PTHREAD_LIB} DEPENDS - ${tablegen_deps} + intrinsics_gen ) diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index b89f4436288aa..f85d0fb9f55e3 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -2,10 +2,6 @@ set(LLVM_TARGET_DEFINITIONS Options.td) tablegen(LLVM Options.inc -gen-opt-parser-defs) add_public_tablegen_target(ELFOptionsTableGen) -if(NOT LLD_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_lld_library(lldELF AArch64ErrataFix.cpp Arch/AArch64.cpp @@ -66,5 +62,5 @@ add_lld_library(lldELF DEPENDS ELFOptionsTableGen - ${tablegen_deps} + intrinsics_gen ) diff --git a/lld/MinGW/CMakeLists.txt b/lld/MinGW/CMakeLists.txt index bb0fe4a3887d7..1dc04d73eca65 100644 --- a/lld/MinGW/CMakeLists.txt +++ b/lld/MinGW/CMakeLists.txt @@ -2,10 +2,6 @@ set(LLVM_TARGET_DEFINITIONS Options.td) tablegen(LLVM Options.inc -gen-opt-parser-defs) add_public_tablegen_target(MinGWOptionsTableGen) -if(NOT LLD_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_lld_library(lldMinGW Driver.cpp @@ -19,5 +15,5 @@ add_lld_library(lldMinGW DEPENDS MinGWOptionsTableGen - ${tablegen_deps} + intrinsics_gen ) diff --git a/lld/lib/Core/CMakeLists.txt b/lld/lib/Core/CMakeLists.txt index 2d4d9ded08862..d5e507536b720 100644 --- a/lld/lib/Core/CMakeLists.txt +++ b/lld/lib/Core/CMakeLists.txt @@ -1,7 +1,3 @@ -if(NOT LLD_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_lld_library(lldCore DefinedAtom.cpp Error.cpp @@ -24,5 +20,5 @@ add_lld_library(lldCore ${LLVM_PTHREAD_LIB} DEPENDS - ${tablegen_deps} + intrinsics_gen ) diff --git a/lld/wasm/CMakeLists.txt b/lld/wasm/CMakeLists.txt index d2ba862c1e4a0..cd46f0a826ac9 100644 --- a/lld/wasm/CMakeLists.txt +++ b/lld/wasm/CMakeLists.txt @@ -2,10 +2,6 @@ set(LLVM_TARGET_DEFINITIONS Options.td) tablegen(LLVM Options.inc -gen-opt-parser-defs) add_public_tablegen_target(WasmOptionsTableGen) -if(NOT LLD_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_lld_library(lldWasm Driver.cpp InputChunks.cpp @@ -37,5 +33,5 @@ add_lld_library(lldWasm DEPENDS WasmOptionsTableGen - ${tablegen_deps} + intrinsics_gen ) diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index bf748020ea407..b1c0597cf3b3f 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -64,7 +64,7 @@ endif () # some of these generated headers. This approach is copied from Clang's main # CMakeLists.txt, so it should kept in sync the code in Clang which was added # in llvm-svn 308844. -if(LLVM_ENABLE_MODULES AND NOT LLDB_BUILT_STANDALONE) +if(LLVM_ENABLE_MODULES) list(APPEND LLVM_COMMON_DEPENDS intrinsics_gen) endif() diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt index 7e2f19ed5b09a..bf94361dd6c19 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -1,7 +1,3 @@ -if(NOT LLDB_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_lldb_library(lldbExpression DiagnosticManager.cpp DWARFExpression.cpp @@ -18,7 +14,7 @@ add_lldb_library(lldbExpression UtilityFunction.cpp DEPENDS - ${tablegen_deps} + intrinsics_gen LINK_LIBS lldbCore diff --git a/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt b/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt index 69696b9aa76ad..04f6cdf9d9bd5 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt +++ b/lldb/source/Plugins/ExpressionParser/Clang/CMakeLists.txt @@ -1,7 +1,3 @@ -if(NOT LLDB_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - add_lldb_library(lldbPluginExpressionParserClang ASTResultSynthesizer.cpp ASTStructExtractor.cpp @@ -29,7 +25,7 @@ add_lldb_library(lldbPluginExpressionParserClang NameSearchContext.cpp DEPENDS - ${tablegen_deps} + intrinsics_gen LINK_LIBS lldbCore diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt index c122e09e8febe..9efb2c44d846e 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/CMakeLists.txt @@ -1,8 +1,3 @@ -if(NOT LLDB_BUILT_STANDALONE) - set(tablegen_deps intrinsics_gen) -endif() - - add_lldb_library(lldbPluginRenderScriptRuntime PLUGIN RenderScriptRuntime.cpp RenderScriptExpressionOpts.cpp @@ -10,7 +5,7 @@ add_lldb_library(lldbPluginRenderScriptRuntime PLUGIN RenderScriptScriptGroup.cpp DEPENDS - ${tablegen_deps} + intrinsics_gen LINK_LIBS lldbBreakpoint From 0dfa4a83fad43f95c90dd67cb23f63baaa907bd1 Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Fri, 17 Jul 2020 16:47:41 -0700 Subject: [PATCH 688/771] Revert "[PGO][PGSO] Add profile guided size optimization to loop vectorization legality." This reverts commit 30c382a7c6607a7d898730f8d288768110cdf1d2. See https://crbug.com/1106813. --- .../Vectorize/LoopVectorizationLegality.h | 9 +-- .../Vectorize/LoopVectorizationLegality.cpp | 7 +- .../Transforms/Vectorize/LoopVectorize.cpp | 33 ++++------ llvm/test/Transforms/LoopVectorize/optsize.ll | 65 +------------------ 4 files changed, 15 insertions(+), 99 deletions(-) diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h index 7235aa5861120..c6c3450f77608 100644 --- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h +++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h @@ -202,10 +202,9 @@ class LoopVectorizationLegality { Function *F, std::function *GetLAA, LoopInfo *LI, OptimizationRemarkEmitter *ORE, LoopVectorizationRequirements *R, LoopVectorizeHints *H, DemandedBits *DB, - AssumptionCache *AC, BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI) + AssumptionCache *AC) : TheLoop(L), LI(LI), PSE(PSE), TTI(TTI), TLI(TLI), DT(DT), - GetLAA(GetLAA), ORE(ORE), Requirements(R), Hints(H), DB(DB), AC(AC), - BFI(BFI), PSI(PSI) {} + GetLAA(GetLAA), ORE(ORE), Requirements(R), Hints(H), DB(DB), AC(AC) {} /// ReductionList contains the reduction descriptors for all /// of the reductions that were found in the loop. @@ -479,10 +478,6 @@ class LoopVectorizationLegality { /// Assume instructions in predicated blocks must be dropped if the CFG gets /// flattened. SmallPtrSet ConditionalAssumes; - - /// BFI and PSI are used to check for profile guided size optimizations. - BlockFrequencyInfo *BFI; - ProfileSummaryInfo *PSI; }; } // namespace llvm diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp index 120b544808bed..23613775d896d 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp @@ -20,7 +20,6 @@ #include "llvm/Analysis/VectorUtils.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/PatternMatch.h" -#include "llvm/Transforms/Utils/SizeOpts.h" #include "llvm/Transforms/Vectorize/LoopVectorize.h" using namespace llvm; @@ -413,11 +412,7 @@ int LoopVectorizationLegality::isConsecutivePtr(Value *Ptr) { const ValueToValueMap &Strides = getSymbolicStrides() ? *getSymbolicStrides() : ValueToValueMap(); - Function *F = TheLoop->getHeader()->getParent(); - bool OptForSize = F->hasOptSize() || - llvm::shouldOptimizeForSize(TheLoop->getHeader(), PSI, BFI, - PGSOQueryType::IRPass); - bool CanAddPredicate = !OptForSize; + bool CanAddPredicate = !TheLoop->getHeader()->getParent()->hasOptSize(); int Stride = getPtrStride(PSE, Ptr, TheLoop, Strides, CanAddPredicate, false); if (Stride == 1 || Stride == -1) return Stride; diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index e9e0ccb8b2ee7..7f13a689cedbd 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -395,13 +395,11 @@ class InnerLoopVectorizer { const TargetTransformInfo *TTI, AssumptionCache *AC, OptimizationRemarkEmitter *ORE, unsigned VecWidth, unsigned UnrollFactor, LoopVectorizationLegality *LVL, - LoopVectorizationCostModel *CM, BlockFrequencyInfo *BFI, - ProfileSummaryInfo *PSI) + LoopVectorizationCostModel *CM) : OrigLoop(OrigLoop), PSE(PSE), LI(LI), DT(DT), TLI(TLI), TTI(TTI), AC(AC), ORE(ORE), VF(VecWidth), UF(UnrollFactor), Builder(PSE.getSE()->getContext()), - VectorLoopValueMap(UnrollFactor, VecWidth), Legal(LVL), Cost(CM), - BFI(BFI), PSI(PSI) {} + VectorLoopValueMap(UnrollFactor, VecWidth), Legal(LVL), Cost(CM) {} virtual ~InnerLoopVectorizer() = default; /// Create a new empty loop. Unlink the old loop and connect the new one. @@ -781,10 +779,6 @@ class InnerLoopVectorizer { // Vector of original scalar PHIs whose corresponding widened PHIs need to be // fixed up at the end of vector code generation. SmallVector OrigPHIsToFix; - - /// BFI and PSI are used to check for profile guided size optimizations. - BlockFrequencyInfo *BFI; - ProfileSummaryInfo *PSI; }; class InnerLoopUnroller : public InnerLoopVectorizer { @@ -795,10 +789,9 @@ class InnerLoopUnroller : public InnerLoopVectorizer { const TargetTransformInfo *TTI, AssumptionCache *AC, OptimizationRemarkEmitter *ORE, unsigned UnrollFactor, LoopVectorizationLegality *LVL, - LoopVectorizationCostModel *CM, BlockFrequencyInfo *BFI, - ProfileSummaryInfo *PSI) + LoopVectorizationCostModel *CM) : InnerLoopVectorizer(OrigLoop, PSE, LI, DT, TLI, TTI, AC, ORE, 1, - UnrollFactor, LVL, CM, BFI, PSI) {} + UnrollFactor, LVL, CM) {} private: Value *getBroadcastInstrs(Value *V) override; @@ -2761,9 +2754,7 @@ void InnerLoopVectorizer::emitSCEVChecks(Loop *L, BasicBlock *Bypass) { if (C->isZero()) return; - assert(!(SCEVCheckBlock->getParent()->hasOptSize() || - llvm::shouldOptimizeForSize(L->getHeader(), PSI, BFI, - PGSOQueryType::IRPass)) && + assert(!SCEVCheckBlock->getParent()->hasOptSize() && "Cannot SCEV check stride or overflow when optimizing for size"); SCEVCheckBlock->setName("vector.scevcheck"); @@ -2809,9 +2800,7 @@ void InnerLoopVectorizer::emitMemRuntimeChecks(Loop *L, BasicBlock *Bypass) { assert(MemRuntimeCheck && "no RT checks generated although RtPtrChecking " "claimed checks are required"); - if (MemCheckBlock->getParent()->hasOptSize() || - llvm::shouldOptimizeForSize(L->getHeader(), PSI, BFI, - PGSOQueryType::IRPass)) { + if (MemCheckBlock->getParent()->hasOptSize()) { assert(Cost->Hints->getForce() == LoopVectorizeHints::FK_Enabled && "Cannot emit memory checks when optimizing for size, unless forced " "to vectorize."); @@ -7740,7 +7729,7 @@ static bool processLoopInVPlanNativePath( LVP.setBestPlan(VF.Width, 1); InnerLoopVectorizer LB(L, PSE, LI, DT, TLI, TTI, AC, ORE, VF.Width, 1, LVL, - &CM, BFI, PSI); + &CM); LLVM_DEBUG(dbgs() << "Vectorizing outer loop in \"" << L->getHeader()->getParent()->getName() << "\"\n"); LVP.executePlan(LB, DT); @@ -7804,7 +7793,7 @@ bool LoopVectorizePass::processLoop(Loop *L) { // Check if it is legal to vectorize the loop. LoopVectorizationRequirements Requirements(*ORE); LoopVectorizationLegality LVL(L, PSE, DT, TTI, TLI, AA, F, GetLAA, LI, ORE, - &Requirements, &Hints, DB, AC, BFI, PSI); + &Requirements, &Hints, DB, AC); if (!LVL.canVectorize(EnableVPlanNativePath)) { LLVM_DEBUG(dbgs() << "LV: Not vectorizing: Cannot prove legality.\n"); Hints.emitRemarkWithHints(); @@ -8004,8 +7993,8 @@ bool LoopVectorizePass::processLoop(Loop *L) { assert(IC > 1 && "interleave count should not be 1 or 0"); // If we decided that it is not legal to vectorize the loop, then // interleave it. - InnerLoopUnroller Unroller(L, PSE, LI, DT, TLI, TTI, AC, ORE, IC, &LVL, &CM, - BFI, PSI); + InnerLoopUnroller Unroller(L, PSE, LI, DT, TLI, TTI, AC, ORE, IC, &LVL, + &CM); LVP.executePlan(Unroller, DT); ORE->emit([&]() { @@ -8017,7 +8006,7 @@ bool LoopVectorizePass::processLoop(Loop *L) { } else { // If we decided that it is *legal* to vectorize the loop, then do it. InnerLoopVectorizer LB(L, PSE, LI, DT, TLI, TTI, AC, ORE, VF.Width, IC, - &LVL, &CM, BFI, PSI); + &LVL, &CM); LVP.executePlan(LB, DT); ++LoopsVectorized; diff --git a/llvm/test/Transforms/LoopVectorize/optsize.ll b/llvm/test/Transforms/LoopVectorize/optsize.ll index b4233e6751cbc..0e88f362746fb 100644 --- a/llvm/test/Transforms/LoopVectorize/optsize.ll +++ b/llvm/test/Transforms/LoopVectorize/optsize.ll @@ -121,38 +121,6 @@ for.body29: br i1 %cmp26, label %for.body29, label %for.cond.cleanup28 } -define void @pr43371_pgso() !prof !14 { -; -; CHECK-LABEL: @pr43371_pgso -; CHECK-NOT: vector.scevcheck -; -; We do not want to generate SCEV predicates when optimising for size, because -; that will lead to extra code generation such as the SCEV overflow runtime -; checks. Not generating SCEV predicates can still result in vectorisation as -; the non-consecutive loads/stores can be scalarized: -; -; CHECK: vector.body: -; CHECK: store i16 0, i16* %{{.*}}, align 1 -; CHECK: store i16 0, i16* %{{.*}}, align 1 -; CHECK: br i1 {{.*}}, label %vector.body -; -entry: - br label %for.body29 - -for.cond.cleanup28: - unreachable - -for.body29: - %i24.0170 = phi i16 [ 0, %entry], [ %inc37, %for.body29] - %add33 = add i16 undef, %i24.0170 - %idxprom34 = zext i16 %add33 to i32 - %arrayidx35 = getelementptr [2592 x i16], [2592 x i16] * @cm_array, i32 0, i32 %idxprom34 - store i16 0, i16 * %arrayidx35, align 1 - %inc37 = add i16 %i24.0170, 1 - %cmp26 = icmp ult i16 %inc37, 756 - br i1 %cmp26, label %for.body29, label %for.cond.cleanup28 -} - ; PR45526: don't vectorize with fold-tail if first-order-recurrence is live-out. ; define i32 @pr45526() optsize { @@ -186,37 +154,6 @@ exit: ret i32 %for } -define i32 @pr45526_pgso() !prof !14 { -; -; CHECK-LABEL: @pr45526_pgso -; CHECK-NEXT: entry: -; CHECK-NEXT: br label %loop -; CHECK-EMPTY: -; CHECK-NEXT: loop: -; CHECK-NEXT: %piv = phi i32 [ 0, %entry ], [ %pivPlus1, %loop ] -; CHECK-NEXT: %for = phi i32 [ 5, %entry ], [ %pivPlus1, %loop ] -; CHECK-NEXT: %pivPlus1 = add nuw nsw i32 %piv, 1 -; CHECK-NEXT: %cond = icmp ult i32 %piv, 510 -; CHECK-NEXT: br i1 %cond, label %loop, label %exit -; CHECK-EMPTY: -; CHECK-NEXT: exit: -; CHECK-NEXT: %for.lcssa = phi i32 [ %for, %loop ] -; CHECK-NEXT: ret i32 %for.lcssa -; -entry: - br label %loop - -loop: - %piv = phi i32 [ 0, %entry ], [ %pivPlus1, %loop ] - %for = phi i32 [ 5, %entry ], [ %pivPlus1, %loop ] - %pivPlus1 = add nuw nsw i32 %piv, 1 - %cond = icmp ult i32 %piv, 510 - br i1 %cond, label %loop, label %exit - -exit: - ret i32 %for -} - ; PR46228: Vectorize w/o versioning for unit stride under optsize and enabled ; vectorization. @@ -253,7 +190,7 @@ define void @stride1(i16* noalias %B, i32 %BStride) optsize { ; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 2 ; CHECK-NEXT: [[VEC_IND_NEXT]] = add <2 x i32> [[VEC_IND]], ; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i32 [[INDEX_NEXT]], 1026 -; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !21 +; CHECK-NEXT: br i1 [[TMP8]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !19 ; CHECK: middle.block: ; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: From 8e2b4e50f27094b71840bdfc5b8ed7dbd4e85c2c Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 17 Jul 2020 16:36:59 -0700 Subject: [PATCH 689/771] [flang] Support = syntax in compiler directives Accept name=value as part of a !DIR$ compiler directive. These are currently ignored in semantics, but we should recognize more directive forms to facilitate testing. In due course, these placeholding directive parsers will be replaced. Reviewed By: sscalpone Differential Revision: https://reviews.llvm.org/D84077 --- flang/include/flang/Parser/dump-parse-tree.h | 1 + flang/include/flang/Parser/parse-tree.h | 6 +++++- flang/lib/Parser/Fortran-parsers.cpp | 4 +++- flang/lib/Parser/unparse.cpp | 8 +++++++- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 36e593eb3b781..02da3f53b44e0 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -222,6 +222,7 @@ class ParseTreeDumper { NODE(CommonStmt, Block) NODE(parser, CompilerDirective) NODE(CompilerDirective, IgnoreTKR) + NODE(CompilerDirective, NameValue) NODE(parser, ComplexLiteralConstant) NODE(parser, ComplexPart) NODE(parser, ComponentArraySpec) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index d9ecebfc3fdda..4b34d2cd674cc 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3211,8 +3211,12 @@ struct CompilerDirective { TUPLE_CLASS_BOILERPLATE(IgnoreTKR); std::tuple, Name> t; }; + struct NameValue { + TUPLE_CLASS_BOILERPLATE(NameValue); + std::tuple> t; + }; CharBlock source; - std::variant, std::list> u; + std::variant, std::list> u; }; // Legacy extensions diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp index 3192781d4bcc9..f46186323ada1 100644 --- a/flang/lib/Parser/Fortran-parsers.cpp +++ b/flang/lib/Parser/Fortran-parsers.cpp @@ -1173,7 +1173,9 @@ constexpr auto ignore_tkr{ defaulted(parenthesized(some("tkr"_ch))), name))}; TYPE_PARSER( beginDirective >> sourced(construct(ignore_tkr) || - construct("DIR$" >> many(name))) / + construct("DIR$" >> + many(construct( + name, maybe("=" >> digitString64))))) / endDirective) TYPE_PARSER(extension(construct( diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 99792cbf706fa..3b95636fc3e59 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -1761,7 +1761,9 @@ class UnparseVisitor { Word("!DIR$ IGNORE_TKR"); // emitted even if tkr list is empty Walk(" ", tkr, ", "); }, - [&](const std::list &names) { Walk("!DIR$ ", names, " "); }, + [&](const std::list &names) { + Walk("!DIR$ ", names, " "); + }, }, x.u); Put('\n'); @@ -1777,6 +1779,10 @@ class UnparseVisitor { } Walk(std::get(x.t)); } + void Unparse(const CompilerDirective::NameValue &x) { + Walk(std::get(x.t)); + Walk("=", std::get>(x.t)); + } // OpenACC Directives & Clauses void Unparse(const AccAtomicCapture &x) { From 8305a92a4752aff8118b501407cfd158c653e67c Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 17 Jul 2020 16:40:49 -0700 Subject: [PATCH 690/771] [flang] Treat tabs like spaces in formatted input. Reviewed By: sscalpone Differential Revision: https://reviews.llvm.org/D84078 --- flang/runtime/edit-input.cpp | 9 +++++---- flang/runtime/io-stmt.cpp | 10 ++++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/flang/runtime/edit-input.cpp b/flang/runtime/edit-input.cpp index 27e8122d9ae6b..dd708c7bfb913 100644 --- a/flang/runtime/edit-input.cpp +++ b/flang/runtime/edit-input.cpp @@ -34,7 +34,7 @@ static bool EditBOZInput(IoStatementState &io, const DataEdit &edit, void *n, common::UnsignedInt128 value{0}; for (; next; next = io.NextInField(remaining)) { char32_t ch{*next}; - if (ch == ' ') { + if (ch == ' ' || ch == '\t') { continue; } int digit{0}; @@ -101,7 +101,7 @@ bool EditIntegerInput( common::UnsignedInt128 value; for (; next; next = io.NextInField(remaining)) { char32_t ch{*next}; - if (ch == ' ') { + if (ch == ' ' || ch == '\t') { if (edit.modes.editingFlags & blankZero) { ch = '0'; // BZ mode - treat blank as if it were zero } else { @@ -170,7 +170,7 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io, } else if (*next == decimal || (*next >= '0' && *next <= '9')) { for (; next; next = io.NextInField(remaining)) { char32_t ch{*next}; - if (ch == ' ') { + if (ch == ' ' || ch == '\t') { if (edit.modes.editingFlags & blankZero) { ch = '0'; // BZ mode - treat blank as if it were zero } else { @@ -229,7 +229,7 @@ static int ScanRealInput(char *buffer, int bufferSize, IoStatementState &io, return 0; } if (remaining) { - while (next && *next == ' ') { + while (next && (*next == ' ' || *next == '\t')) { next = io.NextInField(remaining); } if (next) { @@ -386,6 +386,7 @@ static bool EditListDirectedDefaultCharacterInput( next = io.NextInField(remaining)) { switch (*next) { case ' ': + case '\t': case ',': case ';': case '/': diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 70fb3f9350bc8..8efda2d09a773 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -353,7 +353,7 @@ std::optional IoStatementState::SkipSpaces( std::optional &remaining) { while (!remaining || *remaining > 0) { if (auto ch{GetCurrentChar()}) { - if (*ch != ' ') { + if (*ch != ' ' && *ch != '\t') { return ch; } HandleRelativePosition(1); @@ -373,6 +373,7 @@ std::optional IoStatementState::NextInField( if (auto next{GetCurrentChar()}) { switch (*next) { case ' ': + case '\t': case ',': case ';': case '/': @@ -415,7 +416,7 @@ std::optional IoStatementState::NextInField( std::optional IoStatementState::GetNextNonBlank() { auto ch{GetCurrentChar()}; - while (ch.value_or(' ') == ' ') { + while (!ch || *ch == ' ' || *ch == '\t') { if (ch) { HandleRelativePosition(1); } else if (!AdvanceRecord()) { @@ -485,7 +486,8 @@ ListDirectedStatementState::GetNextDataEdit( if (!imaginaryPart_) { edit.repeat = std::min(remaining_, maxRepeat); auto ch{io.GetNextNonBlank()}; - if (!ch || *ch == ' ' || *ch == comma) { // "r*" repeated null + if (!ch || *ch == ' ' || *ch == '\t' || *ch == comma) { + // "r*" repeated null edit.descriptor = DataEdit::ListDirectedNullValue; } } @@ -554,7 +556,7 @@ ListDirectedStatementState::GetNextDataEdit( edit.descriptor = DataEdit::ListDirectedNullValue; return edit; } - if (!ch || *ch == ' ' || *ch == comma) { // "r*" null + if (!ch || *ch == ' ' || *ch == '\t' || *ch == comma) { // "r*" null edit.descriptor = DataEdit::ListDirectedNullValue; } edit.repeat = std::min(r, maxRepeat); From b0a971d25cdc9fdb7ca1a21db1d0fd409f58f85a Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 17 Jul 2020 17:02:47 -0700 Subject: [PATCH 691/771] [flang] Prevent bogus runtime I/O error message The runtime was requiring that STATUS='OLD' be explicitly specified on an OPEN statement for a connected unit. There error should issue only if a STATUS= other than 'OLD' is specified; an OPEN with no STATUS= specifier is okay. Reviewed By: sscalpone Differential Revision: https://reviews.llvm.org/D84079 --- flang/runtime/io-stmt.cpp | 9 +++++---- flang/runtime/io-stmt.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/flang/runtime/io-stmt.cpp b/flang/runtime/io-stmt.cpp index 8efda2d09a773..9e89e0c28816d 100644 --- a/flang/runtime/io-stmt.cpp +++ b/flang/runtime/io-stmt.cpp @@ -162,11 +162,12 @@ void OpenStatementState::set_path( } int OpenStatementState::EndIoStatement() { - if (wasExtant_ && status_ != OpenStatus::Old) { - SignalError("OPEN statement for connected unit must have STATUS='OLD'"); + if (wasExtant_ && status_ && *status_ != OpenStatus::Old) { + SignalError("OPEN statement for connected unit may not have STATUS= other " + "than 'OLD'"); } - unit().OpenUnit( - status_, action_, position_, std::move(path_), pathLength_, *this); + unit().OpenUnit(status_.value_or(OpenStatus::Unknown), action_, position_, + std::move(path_), pathLength_, *this); return ExternalIoStatementBase::EndIoStatement(); } diff --git a/flang/runtime/io-stmt.h b/flang/runtime/io-stmt.h index 6f5ca2c481128..da58769ef1143 100644 --- a/flang/runtime/io-stmt.h +++ b/flang/runtime/io-stmt.h @@ -302,7 +302,7 @@ class OpenStatementState : public ExternalIoStatementBase { private: bool wasExtant_; - OpenStatus status_{OpenStatus::Unknown}; + std::optional status_; Position position_{Position::AsIs}; std::optional action_; OwningPtr path_; From 1bbed69059d5ac35c0775e8ed598a34628d8ba6d Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 17 Jul 2020 17:29:20 -0700 Subject: [PATCH 692/771] [sanitizer] Another attempt to fix protoent test Now we are going to pick name and index based on output of getprotoent_r. --- .../sanitizer_common/TestCases/Linux/protoent.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/protoent.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/protoent.cpp index a10fd114022c9..003790067d1b1 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/protoent.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/protoent.cpp @@ -7,6 +7,10 @@ #include #include #include +#include + +std::string any_name; +int total_count; void print_protoent(protoent *curr_entry) { fprintf(stderr, "%s (%d)\n", curr_entry->p_name, curr_entry->p_proto); @@ -23,6 +27,8 @@ void print_all_protoent() { protoent *curr_entry; while (getprotoent_r(&entry, buf, sizeof(buf), &curr_entry) != ENOENT && curr_entry) { + ++total_count; + any_name = curr_entry->p_name; print_protoent(curr_entry); } } @@ -51,10 +57,13 @@ int main() { fprintf(stderr, "All protoent\n"); print_all_protoent(); + if (!total_count) + return 0; + fprintf(stderr, "Protoent by name\n"); - print_protoent_by_name("ipv6"); + print_protoent_by_name(any_name.c_str()); fprintf(stderr, "Protoent by num\n"); - print_protoent_by_num(17); + print_protoent_by_num(total_count / 2); return 0; } From 31eb83496fb4e41e322e19f162aeae885ed91301 Mon Sep 17 00:00:00 2001 From: Logan Smith Date: Thu, 16 Jul 2020 20:36:46 -0700 Subject: [PATCH 693/771] [llvm][NFC] Add missing 'override's in unittests/ --- llvm/unittests/ADT/TwineTest.cpp | 2 +- .../DebugInfo/CodeView/RandomAccessVisitorTest.cpp | 4 ++-- llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp | 10 +++++----- llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp | 2 +- llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp | 2 +- .../Orc/LegacyCompileOnDemandLayerTest.cpp | 2 +- .../Orc/RTDyldObjectLinkingLayerTest.cpp | 4 ++-- llvm/unittests/IR/LegacyPassManagerTest.cpp | 4 ++-- llvm/unittests/IR/ModuleTest.cpp | 2 +- llvm/unittests/ProfileData/InstrProfTest.cpp | 6 +++--- llvm/unittests/Support/CrashRecoveryTest.cpp | 2 +- llvm/unittests/Support/ELFAttributeParserTest.cpp | 2 +- llvm/unittests/Support/FileCheckTest.cpp | 2 +- llvm/unittests/Transforms/Utils/LocalTest.cpp | 2 +- llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp | 2 +- llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp | 2 +- .../tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp | 2 +- 17 files changed, 26 insertions(+), 26 deletions(-) diff --git a/llvm/unittests/ADT/TwineTest.cpp b/llvm/unittests/ADT/TwineTest.cpp index a717036c13645..52cec68210b7d 100644 --- a/llvm/unittests/ADT/TwineTest.cpp +++ b/llvm/unittests/ADT/TwineTest.cpp @@ -105,7 +105,7 @@ TEST(TwineTest, LazyEvaluation) { explicit formatter(int &Count) : FormatAdapter(0), Count(Count) {} int &Count; - void format(raw_ostream &OS, StringRef Style) { ++Count; } + void format(raw_ostream &OS, StringRef Style) override { ++Count; } }; int Count = 0; diff --git a/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp b/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp index 2e95465fb5ac7..cbf8d47c6471b 100644 --- a/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp +++ b/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp @@ -64,11 +64,11 @@ namespace { class MockCallbacks : public TypeVisitorCallbacks { public: - virtual Error visitTypeBegin(CVType &CVR, TypeIndex Index) { + Error visitTypeBegin(CVType &CVR, TypeIndex Index) override { Indices.push_back(Index); return Error::success(); } - virtual Error visitKnownRecord(CVType &CVR, ArrayRecord &AR) { + Error visitKnownRecord(CVType &CVR, ArrayRecord &AR) override { VisitedRecords.push_back(AR); RawRecords.push_back(CVR); return Error::success(); diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp index f4ea34d02094a..26fb8e824923f 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugLineTest.cpp @@ -126,7 +126,7 @@ struct DebugLineBasicFixture : public Test, public CommonFixture {}; struct DebugLineParameterisedFixture : public TestWithParam>, public CommonFixture { - void SetUp() { std::tie(Version, Format) = GetParam(); } + void SetUp() override { std::tie(Version, Format) = GetParam(); } uint16_t Version; DwarfFormat Format; @@ -328,7 +328,7 @@ TEST_F(DebugLineBasicFixture, ErrorForReservedLength) { struct DebugLineUnsupportedVersionFixture : public TestWithParam, public CommonFixture { - void SetUp() { Version = GetParam(); } + void SetUp() override { Version = GetParam(); } uint16_t Version; }; @@ -1384,7 +1384,7 @@ struct TruncatedPrologueFixture : public TestWithParam< std::tuple>, public CommonFixture { - void SetUp() { + void SetUp() override { std::tie(Length, ExpectedOffset, Version, Format, ExpectedErr) = GetParam(); } @@ -1554,7 +1554,7 @@ struct TruncatedStandardOpcodeFixture : public TestWithParam< std::tuple>, public TruncatedOpcodeFixtureBase { - void SetUp() { + void SetUp() override { std::tie(BodyLength, Opcode, Operands, ExpectedOutput, ExpectedErr) = GetParam(); } @@ -1564,7 +1564,7 @@ struct TruncatedExtendedOpcodeFixture : public TestWithParam>, public TruncatedOpcodeFixtureBase { - void SetUp() { + void SetUp() override { std::tie(BodyLength, OpcodeLength, Opcode, Operands, ExpectedOutput, ExpectedErr) = GetParam(); } diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp index 4df77baf9471c..0a0b8084f65f0 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp @@ -125,7 +125,7 @@ using ParamType = std::tuple, uint64_t, bool>; struct FormSkipValueFixtureBase : public testing::TestWithParam { - void SetUp() { + void SetUp() override { std::tie(Fm, Version, AddrSize, Dwarf, InitialData, ExpectedSkipped, ExpectedResult) = GetParam(); } diff --git a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp index b4e8a8302d3bd..6f6e1d43af93d 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/CoreAPIsTest.cpp @@ -1044,7 +1044,7 @@ TEST_F(CoreAPIsStandardTest, GeneratorTest) { TestGenerator(SymbolMap Symbols) : Symbols(std::move(Symbols)) {} Error tryToGenerate(LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, - const SymbolLookupSet &Names) { + const SymbolLookupSet &Names) override { SymbolMap NewDefs; for (const auto &KV : Names) { diff --git a/llvm/unittests/ExecutionEngine/Orc/LegacyCompileOnDemandLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LegacyCompileOnDemandLayerTest.cpp index 59cd11c5e5a68..a13d8bdeeeb38 100644 --- a/llvm/unittests/ExecutionEngine/Orc/LegacyCompileOnDemandLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/LegacyCompileOnDemandLayerTest.cpp @@ -17,7 +17,7 @@ namespace { class DummyTrampolinePool : public orc::TrampolinePool { public: - Expected getTrampoline() { + Expected getTrampoline() override { llvm_unreachable("Unimplemented"); } }; diff --git a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp index 4a192c1f28ac3..c9c15aa3dffd7 100644 --- a/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp +++ b/llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp @@ -117,7 +117,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) { public: FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} - Expected operator()(Module &M) { + Expected operator()(Module &M) override { auto *Foo = M.getFunction("foo"); assert(Foo && "Expected function Foo not found"); Foo->setVisibility(GlobalValue::HiddenVisibility); @@ -187,7 +187,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) { public: FunkySimpleCompiler(TargetMachine &TM) : SimpleCompiler(TM) {} - Expected operator()(Module &M) { + Expected operator()(Module &M) override { Function *BarImpl = Function::Create( FunctionType::get(Type::getVoidTy(M.getContext()), {}, false), GlobalValue::ExternalLinkage, "bar", &M); diff --git a/llvm/unittests/IR/LegacyPassManagerTest.cpp b/llvm/unittests/IR/LegacyPassManagerTest.cpp index 8dda94b1b0326..72ac4be229974 100644 --- a/llvm/unittests/IR/LegacyPassManagerTest.cpp +++ b/llvm/unittests/IR/LegacyPassManagerTest.cpp @@ -355,12 +355,12 @@ namespace llvm { struct CustomOptPassGate : public OptPassGate { bool Skip; CustomOptPassGate(bool Skip) : Skip(Skip) { } - bool shouldRunPass(const Pass *P, StringRef IRDescription) { + bool shouldRunPass(const Pass *P, StringRef IRDescription) override { if (P->getPassKind() == PT_Module) return !Skip; return OptPassGate::shouldRunPass(P, IRDescription); } - bool isEnabled() const { return true; } + bool isEnabled() const override { return true; } }; // Optional module pass. diff --git a/llvm/unittests/IR/ModuleTest.cpp b/llvm/unittests/IR/ModuleTest.cpp index 9fb9b8b057a5e..4e2e394a92504 100644 --- a/llvm/unittests/IR/ModuleTest.cpp +++ b/llvm/unittests/IR/ModuleTest.cpp @@ -56,7 +56,7 @@ TEST(ModuleTest, randomNumberGenerator) { static char ID; struct DummyPass : ModulePass { DummyPass() : ModulePass(ID) {} - bool runOnModule(Module &) { return true; } + bool runOnModule(Module &) override { return true; } } DP; Module M("R", Context); diff --git a/llvm/unittests/ProfileData/InstrProfTest.cpp b/llvm/unittests/ProfileData/InstrProfTest.cpp index 3e862aafcf05c..d94906991b0c6 100644 --- a/llvm/unittests/ProfileData/InstrProfTest.cpp +++ b/llvm/unittests/ProfileData/InstrProfTest.cpp @@ -39,7 +39,7 @@ struct InstrProfTest : ::testing::Test { InstrProfWriter Writer; std::unique_ptr Reader; - void SetUp() { Writer.setOutputSparse(false); } + void SetUp() override { Writer.setOutputSparse(false); } void readProfile(std::unique_ptr Profile, std::unique_ptr Remapping = nullptr) { @@ -51,12 +51,12 @@ struct InstrProfTest : ::testing::Test { }; struct SparseInstrProfTest : public InstrProfTest { - void SetUp() { Writer.setOutputSparse(true); } + void SetUp() override { Writer.setOutputSparse(true); } }; struct MaybeSparseInstrProfTest : public InstrProfTest, public ::testing::WithParamInterface { - void SetUp() { Writer.setOutputSparse(GetParam()); } + void SetUp() override { Writer.setOutputSparse(GetParam()); } }; TEST_P(MaybeSparseInstrProfTest, write_and_read_empty_profile) { diff --git a/llvm/unittests/Support/CrashRecoveryTest.cpp b/llvm/unittests/Support/CrashRecoveryTest.cpp index 798ed20145d87..6a62c7cab9d83 100644 --- a/llvm/unittests/Support/CrashRecoveryTest.cpp +++ b/llvm/unittests/Support/CrashRecoveryTest.cpp @@ -39,7 +39,7 @@ TEST(CrashRecoveryTest, Basic) { struct IncrementGlobalCleanup : CrashRecoveryContextCleanup { IncrementGlobalCleanup(CrashRecoveryContext *CRC) : CrashRecoveryContextCleanup(CRC) {} - virtual void recoverResources() { ++GlobalInt; } + void recoverResources() override { ++GlobalInt; } }; static void noop() {} diff --git a/llvm/unittests/Support/ELFAttributeParserTest.cpp b/llvm/unittests/Support/ELFAttributeParserTest.cpp index 8234d4ee176f2..5eaed39a71057 100644 --- a/llvm/unittests/Support/ELFAttributeParserTest.cpp +++ b/llvm/unittests/Support/ELFAttributeParserTest.cpp @@ -17,7 +17,7 @@ static const TagNameMap emptyTagNameMap; // This class is used to test the common part of the ELF attribute section. class AttributeHeaderParser : public ELFAttributeParser { - Error handler(uint64_t tag, bool &handled) { + Error handler(uint64_t tag, bool &handled) override { // Treat all attributes as handled. handled = true; return Error::success(); diff --git a/llvm/unittests/Support/FileCheckTest.cpp b/llvm/unittests/Support/FileCheckTest.cpp index 92975dcd76b74..8cf823425fc37 100644 --- a/llvm/unittests/Support/FileCheckTest.cpp +++ b/llvm/unittests/Support/FileCheckTest.cpp @@ -104,7 +104,7 @@ struct ExpressionFormatParameterisedFixture SourceMgr SM; - void SetUp() { + void SetUp() override { ExpressionFormat::Kind Kind = GetParam(); AllowHex = Kind == ExpressionFormat::Kind::HexLower || Kind == ExpressionFormat::Kind::HexUpper; diff --git a/llvm/unittests/Transforms/Utils/LocalTest.cpp b/llvm/unittests/Transforms/Utils/LocalTest.cpp index 3862a418603b2..3dec930a27271 100644 --- a/llvm/unittests/Transforms/Utils/LocalTest.cpp +++ b/llvm/unittests/Transforms/Utils/LocalTest.cpp @@ -489,7 +489,7 @@ struct SalvageDebugInfoTest : ::testing::Test { std::unique_ptr M; Function *F = nullptr; - void SetUp() { + void SetUp() override { M = parseIR(C, R"( define void @f() !dbg !8 { diff --git a/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp b/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp index ef53a70aeea05..6bb083b4d2bf7 100644 --- a/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp +++ b/llvm/unittests/tools/llvm-cfi-verify/FileAnalysis.cpp @@ -65,7 +65,7 @@ class BasicFileAnalysisTest : public ::testing::Test { BasicFileAnalysisTest(StringRef Trip) : SuccessfullyInitialised(false), Analysis(Trip) {} protected: - virtual void SetUp() { + void SetUp() override { IgnoreDWARFFlag = true; SuccessfullyInitialised = true; if (auto Err = Analysis.initialiseDisassemblyMembers()) { diff --git a/llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp b/llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp index a57958d60e68b..954c113b915e4 100644 --- a/llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp +++ b/llvm/unittests/tools/llvm-cfi-verify/GraphBuilder.cpp @@ -124,7 +124,7 @@ class ELFx86TestFileAnalysis : public FileAnalysis { class BasicGraphBuilderTest : public ::testing::Test { protected: - virtual void SetUp() { + void SetUp() override { IgnoreDWARFFlag = true; SuccessfullyInitialised = true; if (auto Err = Analysis.initialiseDisassemblyMembers()) { diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp index 298a54abffc88..dcc9617065b03 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp @@ -29,7 +29,7 @@ using testing::UnorderedElementsAre; class X86SnippetRepetitorTest : public X86TestBase { protected: - void SetUp() { + void SetUp() override { TM = State.createTargetMachine(); Context = std::make_unique(); Mod = std::make_unique("X86SnippetRepetitorTest", *Context); From 3ee7fe4cfda1169786f4d2595cb2d51e31bead08 Mon Sep 17 00:00:00 2001 From: Logan Smith Date: Thu, 16 Jul 2020 20:38:41 -0700 Subject: [PATCH 694/771] [llvm][NFC] Add missing 'override's --- llvm/include/llvm/ExecutionEngine/JITSymbol.h | 2 +- llvm/include/llvm/ExecutionEngine/Orc/Speculation.h | 2 +- llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp | 4 ++-- llvm/tools/llvm-jitlink/llvm-jitlink.cpp | 2 +- llvm/tools/llvm-pdbutil/FormatUtil.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/JITSymbol.h b/llvm/include/llvm/ExecutionEngine/JITSymbol.h index 6f0030a18f475..9bbdd21f77de1 100644 --- a/llvm/include/llvm/ExecutionEngine/JITSymbol.h +++ b/llvm/include/llvm/ExecutionEngine/JITSymbol.h @@ -429,7 +429,7 @@ class LegacyJITSymbolResolver : public JITSymbolResolver { virtual JITSymbol findSymbol(const std::string &Name) = 0; private: - virtual void anchor(); + void anchor() override; }; } // end namespace llvm diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h b/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h index d8213d3b35e8f..a6537dd3093bd 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/Speculation.h @@ -185,7 +185,7 @@ class IRSpeculationLayer : public IRLayer { : IRLayer(ES, BaseLayer.getManglingOptions()), NextLayer(BaseLayer), S(Spec), Mangle(Mangle), QueryAnalysis(Interpreter) {} - void emit(MaterializationResponsibility R, ThreadSafeModule TSM); + void emit(MaterializationResponsibility R, ThreadSafeModule TSM) override; private: TargetAndLikelies diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp index 21925726072e3..7888c2fcbdbd9 100644 --- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -18,7 +18,7 @@ class JITDylibSearchOrderResolver : public JITSymbolResolver { public: JITDylibSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {} - void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) { + void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override { auto &ES = MR.getTargetJITDylib().getExecutionSession(); SymbolLookupSet InternedSymbols; @@ -55,7 +55,7 @@ class JITDylibSearchOrderResolver : public JITSymbolResolver { RegisterDependencies); } - Expected getResponsibilitySet(const LookupSet &Symbols) { + Expected getResponsibilitySet(const LookupSet &Symbols) override { LookupSet Result; for (auto &KV : MR.getSymbols()) { diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp index b44a56e0ac925..04132f0769662 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink.cpp @@ -435,7 +435,7 @@ Session::Session(Triple TT, Error &Err) public: JITLinkSessionPlugin(Session &S) : S(S) {} void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT, - PassConfiguration &PassConfig) { + PassConfiguration &PassConfig) override { S.modifyPassConfig(TT, PassConfig); } diff --git a/llvm/tools/llvm-pdbutil/FormatUtil.h b/llvm/tools/llvm-pdbutil/FormatUtil.h index 1a006844e011a..133a0eb40e121 100644 --- a/llvm/tools/llvm-pdbutil/FormatUtil.h +++ b/llvm/tools/llvm-pdbutil/FormatUtil.h @@ -123,7 +123,7 @@ struct EndianAdapter final explicit EndianAdapter(EndianType &&Item) : FormatAdapter(std::move(Item)) {} - void format(llvm::raw_ostream &Stream, StringRef Style) { + void format(llvm::raw_ostream &Stream, StringRef Style) override { format_provider::format(static_cast(this->Item), Stream, Style); } }; From 105056045d9ab0b1a49781a18129ada48893452e Mon Sep 17 00:00:00 2001 From: Logan Smith Date: Thu, 16 Jul 2020 20:39:45 -0700 Subject: [PATCH 695/771] [clang][NFC] Add a missing 'override' --- clang/unittests/CrossTU/CrossTranslationUnitTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/CrossTU/CrossTranslationUnitTest.cpp b/clang/unittests/CrossTU/CrossTranslationUnitTest.cpp index 5495f27f5b32a..4e6fbeee86a3f 100644 --- a/clang/unittests/CrossTU/CrossTranslationUnitTest.cpp +++ b/clang/unittests/CrossTU/CrossTranslationUnitTest.cpp @@ -29,7 +29,7 @@ class CTUASTConsumer : public clang::ASTConsumer { explicit CTUASTConsumer(clang::CompilerInstance &CI, bool *Success) : CTU(CI), Success(Success) {} - void HandleTranslationUnit(ASTContext &Ctx) { + void HandleTranslationUnit(ASTContext &Ctx) override { auto FindFInTU = [](const TranslationUnitDecl *TU) { const FunctionDecl *FD = nullptr; for (const Decl *D : TU->decls()) { From 176a6e7abe33d58a65ce9cfac15fe320962e7b6e Mon Sep 17 00:00:00 2001 From: Kuba Mracek Date: Fri, 17 Jul 2020 17:39:43 -0700 Subject: [PATCH 696/771] [asan] Use dynamic shadow memory position on Apple Silicon macOS This is needed because macOS on Apple Silicon has some reserved pages inside the "regular" shadow memory location, and mapping over that location fails. Differential Revision: https://reviews.llvm.org/D82912 --- compiler-rt/lib/asan/asan_mapping.h | 2 ++ llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp | 3 +++ .../Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll | 4 +++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h index 36e2cb5364f3a..27598171fc29b 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/compiler-rt/lib/asan/asan_mapping.h @@ -206,6 +206,8 @@ static const u64 kMyriadCacheBitMask32 = 0x40000000ULL; #else # if SANITIZER_IOS # define SHADOW_OFFSET __asan_shadow_memory_dynamic_address +# elif SANITIZER_MAC && defined(__aarch64__) +# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address # elif defined(__aarch64__) # define SHADOW_OFFSET kAArch64_ShadowOffset64 # elif defined(__powerpc64__) diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp index 7516a64c6a354..647d25e6a24e0 100644 --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -434,6 +434,7 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize, bool IsKasan) { bool IsAndroid = TargetTriple.isAndroid(); bool IsIOS = TargetTriple.isiOS() || TargetTriple.isWatchOS(); + bool IsMacOS = TargetTriple.isMacOSX(); bool IsFreeBSD = TargetTriple.isOSFreeBSD(); bool IsNetBSD = TargetTriple.isOSNetBSD(); bool IsPS4CPU = TargetTriple.isPS4CPU(); @@ -510,6 +511,8 @@ static ShadowMapping getShadowMapping(Triple &TargetTriple, int LongSize, Mapping.Offset = kMIPS64_ShadowOffset64; else if (IsIOS) Mapping.Offset = kDynamicShadowSentinel; + else if (IsMacOS && IsAArch64) + Mapping.Offset = kDynamicShadowSentinel; else if (IsAArch64) Mapping.Offset = kAArch64_ShadowOffset64; else diff --git a/llvm/test/Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll b/llvm/test/Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll index 391693c2c6f62..7d6b84144e9f8 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll @@ -8,8 +8,10 @@ ; RUN: opt -asan -asan-module -mtriple=i386-apple-ios-simulator --data-layout="e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 ; RUN: opt -asan -asan-module -mtriple=x86_64-apple-ios-simulator --data-layout="e-m:o-i64:64-f80:128-n8:16:32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 ; -; // macOS does not use dynamic shadow placement +; // macOS does not use dynamic shadow placement on x86_64 ; RUN: opt -asan -asan-module -mtriple=x86_64-apple-macosx --data-layout="e-m:o-i64:64-f80:128-n8:16:32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-NONDYNAMIC -DPTR_SIZE=64 +; // macOS does use dynamic shadow placement on arm64 +; RUN: opt -asan -asan-module -mtriple=arm64-apple-macosx --data-layout="e-m:o-i64:64-i128:128-n32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 define i32 @test_load(i32* %a) sanitize_address { ; First instrumentation in the function must be to load the dynamic shadow From 3b55bfad2a3b7dba8815e043fcd9a2c0cb7b2987 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Fri, 17 Jul 2020 14:56:51 -0700 Subject: [PATCH 697/771] [llvm-jitlink] Add suppport for testing GOT entries and stubs for ELF. This enables regression testing of GOT and stub handling with llvm-jitlink. --- llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp | 71 ++++++++++++++++++- .../tools/llvm-jitlink/llvm-jitlink-macho.cpp | 6 -- 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp index 1b74f1016ae99..beb73fb8edf71 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp @@ -20,6 +20,50 @@ using namespace llvm; using namespace llvm::jitlink; +static bool isELFGOTSection(Section &S) { return S.getName() == "$__GOT"; } + +static bool isELFStubsSection(Section &S) { return S.getName() == "$__STUBS"; } + +static Expected getFirstRelocationEdge(LinkGraph &G, Block &B) { + auto EItr = std::find_if(B.edges().begin(), B.edges().end(), + [](Edge &E) { return E.isRelocation(); }); + if (EItr == B.edges().end()) + return make_error("GOT entry in " + G.getName() + ", \"" + + B.getSection().getName() + + "\" has no relocations", + inconvertibleErrorCode()); + return *EItr; +} + +static Expected getELFGOTTarget(LinkGraph &G, Block &B) { + auto E = getFirstRelocationEdge(G, B); + if (!E) + return E.takeError(); + auto &TargetSym = E->getTarget(); + if (!TargetSym.hasName()) + return make_error( + "GOT entry in " + G.getName() + ", \"" + + TargetSym.getBlock().getSection().getName() + + "\" points to anonymous " + "symbol", + inconvertibleErrorCode()); + return TargetSym; +} + +static Expected getELFStubTarget(LinkGraph &G, Block &B) { + auto E = getFirstRelocationEdge(G, B); + if (!E) + return E.takeError(); + auto &GOTSym = E->getTarget(); + if (!GOTSym.isDefined() || !isELFGOTSection(GOTSym.getBlock().getSection())) + return make_error( + "Stubs entry in " + G.getName() + ", \"" + + GOTSym.getBlock().getSection().getName() + + "\" does not point to GOT entry", + inconvertibleErrorCode()); + return getELFGOTTarget(G, GOTSym.getBlock()); +} + namespace llvm { Error registerELFGraphInfo(Session &S, LinkGraph &G) { @@ -53,6 +97,9 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) { "\"", inconvertibleErrorCode()); + bool isGOTSection = isELFGOTSection(Sec); + bool isStubsSection = isELFStubsSection(Sec); + bool SectionContainsContent = false; bool SectionContainsZeroFill = false; @@ -64,7 +111,29 @@ Error registerELFGraphInfo(Session &S, LinkGraph &G) { if (Sym->getAddress() > LastSym->getAddress()) LastSym = Sym; - if (Sym->hasName()) { + if (isGOTSection) { + if (Sym->isSymbolZeroFill()) + return make_error("zero-fill atom in GOT section", + inconvertibleErrorCode()); + + if (auto TS = getELFGOTTarget(G, Sym->getBlock())) + FileInfo.GOTEntryInfos[TS->getName()] = {Sym->getSymbolContent(), + Sym->getAddress()}; + else + return TS.takeError(); + SectionContainsContent = true; + } else if (isStubsSection) { + if (Sym->isSymbolZeroFill()) + return make_error("zero-fill atom in Stub section", + inconvertibleErrorCode()); + + if (auto TS = getELFStubTarget(G, Sym->getBlock())) + FileInfo.StubInfos[TS->getName()] = {Sym->getSymbolContent(), + Sym->getAddress()}; + else + return TS.takeError(); + SectionContainsContent = true; + } else if (Sym->hasName()) { dbgs() << "Symbol: " << Sym->getName() << "\n"; if (Sym->isSymbolZeroFill()) { S.SymbolInfos[Sym->getName()] = {Sym->getSize(), Sym->getAddress()}; diff --git a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp index 18584e55d0f5c..fc70934ea1d59 100644 --- a/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp +++ b/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp @@ -49,12 +49,6 @@ static Expected getMachOGOTTarget(LinkGraph &G, Block &B) { "\" points to anonymous " "symbol", inconvertibleErrorCode()); - if (TargetSym.isDefined() || TargetSym.isAbsolute()) - return make_error( - "GOT entry \"" + TargetSym.getName() + "\" in " + G.getName() + ", \"" + - TargetSym.getBlock().getSection().getName() + - "\" does not point to an external symbol", - inconvertibleErrorCode()); return TargetSym; } From 7c2f2762695896aee5d3c5ebb3943f1a28a5ed3b Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Fri, 17 Jul 2020 17:49:46 -0700 Subject: [PATCH 698/771] [NewPM][ASan] Make ASan tests work under NPM Under NPM, the asan-globals-md analysis is required but cannot be run within the asan function pass due to module analyses not being able to run from a function pass. So this pins all tests using "-asan" to the legacy PM and adds a corresponding RUN line with -passes='require,function(asan)'. Now all tests in Instrumentation/AddressSanitizer pass when -enable-new-pm is by default on. Tests were automatically converted using the following python script and failures were manually fixed up. import sys for i in sys.argv: with open(i, 'r') as f: s = f.read() with open(i, 'w') as f: for l in s.splitlines(): if "RUN:" in l and ' -asan -asan-module ' in l and '\\' not in l: f.write(l.replace(' -asan -asan-module ', ' -asan -asan-module -enable-new-pm=0 ')) f.write('\n') f.write(l.replace(' -asan -asan-module ', " -passes='require,function(asan),module(asan-module)' ")) f.write('\n') elif "RUN:" in l and ' -asan ' in l and '\\' not in l: f.write(l.replace(' -asan ', ' -asan -enable-new-pm=0 ')) f.write('\n') f.write(l.replace(' -asan ', " -passes='require,function(asan)' ")) f.write('\n') else: f.write(l) f.write('\n') See https://bugs.llvm.org/show_bug.cgi?id=46611. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D83921 --- .../AddressSanitizer/X86/asm_cpuid.ll | 3 ++- .../X86/asm_more_registers_than_available.ll | 3 ++- .../AddressSanitizer/X86/bug_11395.ll | 3 ++- .../adaptive_global_redzones.ll | 6 +++-- .../asan-detect-invalid-pointer-pair.ll | 12 ++++++--- .../asan-masked-load-store.ll | 16 ++++++++--- .../AddressSanitizer/asan-vs-gvn.ll | 3 ++- .../asan_address_space_attr.ll | 3 ++- .../AddressSanitizer/basic-msvc64.ll | 3 ++- .../AddressSanitizer/basic-myriad.ll | 3 ++- .../Instrumentation/AddressSanitizer/basic.ll | 9 +++---- .../AddressSanitizer/byval-args.ll | 3 ++- .../AddressSanitizer/debug-info-alloca.ll | 3 ++- .../AddressSanitizer/debug-info-global-var.ll | 3 ++- .../AddressSanitizer/debug_info.ll | 3 ++- .../debug_info_noninstrumented_alloca.ll | 6 +++-- .../debug_info_noninstrumented_alloca2.ll | 6 +++-- .../do-not-instrument-globals-darwin.ll | 3 ++- .../do-not-instrument-globals-linux.ll | 3 ++- .../do-not-instrument-internal-globals.ll | 3 ++- .../do-not-instrument-profiling-globals.ll | 3 ++- .../do-not-instrument-promotable-allocas.ll | 3 ++- .../do-not-instrument-sanitizers.ll | 3 ++- .../do-not-touch-comdat-global.ll | 3 ++- .../do-not-touch-odr-global.ll | 3 ++- .../do-not-touch-threadlocal.ll | 3 ++- .../AddressSanitizer/dynamic-shadow-darwin.ll | 27 ++++++++++++------- .../AddressSanitizer/experiment-call.ll | 3 ++- .../AddressSanitizer/experiment.ll | 3 ++- .../AddressSanitizer/force-dynamic-shadow.ll | 6 +++-- .../AddressSanitizer/freebsd.ll | 21 ++++++++++++--- .../AddressSanitizer/global_addrspace.ll | 3 ++- .../AddressSanitizer/global_cstring_darwin.ll | 3 ++- .../AddressSanitizer/global_lto_merge.ll | 6 +++-- .../AddressSanitizer/global_metadata.ll | 6 +++-- .../AddressSanitizer/global_metadata_array.ll | 12 ++++++--- .../global_metadata_bitcasts.ll | 3 ++- .../global_metadata_darwin.ll | 3 ++- .../global_metadata_external_comdat.ll | 3 ++- .../global_metadata_windows.ll | 3 ++- .../hoist-argument-init-insts.ll | 3 ++- .../instrument-dynamic-allocas.ll | 3 ++- .../AddressSanitizer/instrument-no-return.ll | 3 ++- .../AddressSanitizer/instrument-stack.ll | 6 +++-- .../AddressSanitizer/instrument_global.ll | 6 +++-- .../instrument_initializer_metadata.ll | 6 +++-- .../instrument_load_then_store.ll | 6 +++-- .../instrumentation-with-call-threshold.ll | 15 +++++++---- .../AddressSanitizer/keep_going.ll | 3 ++- .../AddressSanitizer/lifetime-throw.ll | 3 ++- .../AddressSanitizer/lifetime-uar-uas.ll | 12 ++++++--- .../AddressSanitizer/lifetime.ll | 6 +++-- .../AddressSanitizer/local_alias.ll | 12 ++++++--- .../AddressSanitizer/local_stack_base.ll | 3 ++- .../AddressSanitizer/localescape.ll | 6 +++-- .../AddressSanitizer/no-globals.ll | 3 ++- .../AddressSanitizer/odr-check-ignore.ll | 3 ++- .../Instrumentation/AddressSanitizer/ps4.ll | 3 ++- .../AddressSanitizer/scale-offset.ll | 9 ++++--- .../stack-poisoning-and-lifetime-be.ll | 6 +++-- .../stack-poisoning-and-lifetime.ll | 6 +++-- .../stack-poisoning-byval-args.ll | 12 ++++++--- .../AddressSanitizer/stack-poisoning.ll | 6 +++-- .../AddressSanitizer/stack_dynamic_alloca.ll | 4 +++ .../AddressSanitizer/stack_layout.ll | 8 ++++-- .../AddressSanitizer/str-nobuiltin.ll | 3 ++- .../AddressSanitizer/test64.ll | 6 +++-- .../Instrumentation/AddressSanitizer/twice.ll | 3 ++- .../Instrumentation/AddressSanitizer/ubsan.ll | 3 ++- .../AddressSanitizer/win-sorted-sections.ll | 3 ++- .../AddressSanitizer/win-string-literal.ll | 3 ++- .../AddressSanitizer/with-ifunc.ll | 24 ++++++++++++----- llvm/tools/opt/NewPMDriver.cpp | 20 ++++++++++++++ 73 files changed, 305 insertions(+), 130 deletions(-) diff --git a/llvm/test/Instrumentation/AddressSanitizer/X86/asm_cpuid.ll b/llvm/test/Instrumentation/AddressSanitizer/X86/asm_cpuid.ll index cfa91d4da633d..c842f1963d691 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/X86/asm_cpuid.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/X86/asm_cpuid.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -S -o %t.ll +; RUN: opt < %s -asan -enable-new-pm=0 -S -o %t.ll +; RUN: opt < %s -passes='asan-function-pipeline' -S -o %t.ll ; RUN: FileCheck %s < %t.ll ; RUN: llc < %t.ll | FileCheck %s --check-prefix=ASM diff --git a/llvm/test/Instrumentation/AddressSanitizer/X86/asm_more_registers_than_available.ll b/llvm/test/Instrumentation/AddressSanitizer/X86/asm_more_registers_than_available.ll index 7827f3fbf278a..191917581b748 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/X86/asm_more_registers_than_available.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/X86/asm_more_registers_than_available.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -S -o %t.ll +; RUN: opt < %s -asan -enable-new-pm=0 -S -o %t.ll +; RUN: opt < %s -passes='asan-function-pipeline' -S -o %t.ll ; RUN: FileCheck %s < %t.ll ; Don't do stack malloc on functions containing inline assembly on 64-bit diff --git a/llvm/test/Instrumentation/AddressSanitizer/X86/bug_11395.ll b/llvm/test/Instrumentation/AddressSanitizer/X86/bug_11395.ll index 027148a0acd6d..bf9cc11a2b903 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/X86/bug_11395.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/X86/bug_11395.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -S | llc -o /dev/null +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | llc -o /dev/null +; RUN: opt < %s -passes='asan-pipeline' -S | llc -o /dev/null ; The bug manifests as a reg alloc failure: ; error: ran out of registers during register allocation ; ModuleID = 'z.o' diff --git a/llvm/test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll b/llvm/test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll index 2c8df25e53c1c..749f4ad220158 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/adaptive_global_redzones.ll @@ -1,5 +1,7 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-scale=5 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-detect-invalid-pointer-pair.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-detect-invalid-pointer-pair.ll index 3df73e54803ff..5d746c3053c68 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/asan-detect-invalid-pointer-pair.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/asan-detect-invalid-pointer-pair.ll @@ -1,8 +1,14 @@ -; RUN: opt < %s -asan -asan-detect-invalid-pointer-cmp -S \ +; RUN: opt < %s -asan -asan-detect-invalid-pointer-cmp -S -enable-new-pm=0 \ ; RUN: | FileCheck %s --check-prefixes=CMP,NOSUB,ALL -; RUN: opt < %s -asan -asan-detect-invalid-pointer-sub -S \ +; RUN: opt < %s -passes='asan-function-pipeline' -asan-detect-invalid-pointer-cmp -S \ +; RUN: | FileCheck %s --check-prefixes=CMP,NOSUB,ALL +; RUN: opt < %s -asan -asan-detect-invalid-pointer-sub -S -enable-new-pm=0 \ +; RUN: | FileCheck %s --check-prefixes=SUB,NOCMP,ALL +; RUN: opt < %s -passes='asan-function-pipeline' -asan-detect-invalid-pointer-sub -S \ ; RUN: | FileCheck %s --check-prefixes=SUB,NOCMP,ALL -; RUN: opt < %s -asan -asan-detect-invalid-pointer-pair -S \ +; RUN: opt < %s -asan -asan-detect-invalid-pointer-pair -S -enable-new-pm=0 \ +; RUN: | FileCheck %s --check-prefixes=CMP,SUB,ALL +; RUN: opt < %s -passes='asan-function-pipeline' -asan-detect-invalid-pointer-pair -S \ ; RUN: | FileCheck %s --check-prefixes=CMP,SUB,ALL ; Support instrumentation of invalid pointer pair detection. diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-masked-load-store.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-masked-load-store.ll index 1b069255880a9..7a3b69bac2f26 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/asan-masked-load-store.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/asan-masked-load-store.ll @@ -1,10 +1,18 @@ -; RUN: opt < %s -asan -asan-instrumentation-with-call-threshold=0 -S \ +; RUN: opt < %s -asan -asan-instrumentation-with-call-threshold=0 -S -enable-new-pm=0 \ ; RUN: | FileCheck %s -check-prefix=LOAD -check-prefix=STORE -check-prefix=ALL -; RUN: opt < %s -asan -asan-instrumentation-with-call-threshold=0 -asan-instrument-reads=0 -S \ +; RUN: opt < %s -passes='asan-function-pipeline' -asan-instrumentation-with-call-threshold=0 -S \ +; RUN: | FileCheck %s -check-prefix=LOAD -check-prefix=STORE -check-prefix=ALL +; RUN: opt < %s -asan -asan-instrumentation-with-call-threshold=0 -asan-instrument-reads=0 -S -enable-new-pm=0 \ +; RUN: | FileCheck %s -check-prefix=NOLOAD -check-prefix=STORE -check-prefix=ALL +; RUN: opt < %s -passes='asan-function-pipeline' -asan-instrumentation-with-call-threshold=0 -asan-instrument-reads=0 -S \ ; RUN: | FileCheck %s -check-prefix=NOLOAD -check-prefix=STORE -check-prefix=ALL -; RUN: opt < %s -asan -asan-instrumentation-with-call-threshold=0 -asan-instrument-writes=0 -S \ +; RUN: opt < %s -asan -asan-instrumentation-with-call-threshold=0 -asan-instrument-writes=0 -S -enable-new-pm=0 \ ; RUN: | FileCheck %s -check-prefix=LOAD -check-prefix=NOSTORE -check-prefix=ALL -; RUN: opt < %s -asan -asan-instrumentation-with-call-threshold=0 -asan-instrument-reads=0 -asan-instrument-writes=0 -S \ +; RUN: opt < %s -passes='asan-function-pipeline' -asan-instrumentation-with-call-threshold=0 -asan-instrument-writes=0 -S \ +; RUN: | FileCheck %s -check-prefix=LOAD -check-prefix=NOSTORE -check-prefix=ALL +; RUN: opt < %s -asan -asan-instrumentation-with-call-threshold=0 -asan-instrument-reads=0 -asan-instrument-writes=0 -S -enable-new-pm=0 \ +; RUN: | FileCheck %s -check-prefix=NOLOAD -check-prefix=NOSTORE -check-prefix=ALL +; RUN: opt < %s -passes='asan-function-pipeline' -asan-instrumentation-with-call-threshold=0 -asan-instrument-reads=0 -asan-instrument-writes=0 -S \ ; RUN: | FileCheck %s -check-prefix=NOLOAD -check-prefix=NOSTORE -check-prefix=ALL ; Support ASan instrumentation for constant-mask llvm.masked.{load,store} diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan-vs-gvn.ll b/llvm/test/Instrumentation/AddressSanitizer/asan-vs-gvn.ll index f9cfa7af19f62..39e705354fe71 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/asan-vs-gvn.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/asan-vs-gvn.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -basic-aa -gvn -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -basic-aa -gvn -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s "-passes=function(require,gvn),asan-pipeline" -S | FileCheck %s ; ASAN conflicts with load widening iff the widened load accesses data out of bounds ; (while the original unwidened loads do not). ; https://github.com/google/sanitizers/issues/20#issuecomment-136381262 diff --git a/llvm/test/Instrumentation/AddressSanitizer/asan_address_space_attr.ll b/llvm/test/Instrumentation/AddressSanitizer/asan_address_space_attr.ll index 87d72bbe142f7..35744a810ccc7 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/asan_address_space_attr.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/asan_address_space_attr.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-function-pipeline' -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/basic-msvc64.ll b/llvm/test/Instrumentation/AddressSanitizer/basic-msvc64.ll index 2d59b31ef917b..2019011581de9 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/basic-msvc64.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/basic-msvc64.ll @@ -1,6 +1,7 @@ ; Test basic address sanitizer instrumentation. ; -; RUN: opt -asan -asan-module -S < %s | FileCheck %s +; RUN: opt -asan -asan-module -enable-new-pm=0 -S < %s | FileCheck %s +; RUN: opt -passes='asan-pipeline' -S < %s | FileCheck %s target triple = "x86_64-pc-windows-msvc" ; CHECK: @llvm.global_ctors = {{.*}}@asan.module_ctor diff --git a/llvm/test/Instrumentation/AddressSanitizer/basic-myriad.ll b/llvm/test/Instrumentation/AddressSanitizer/basic-myriad.ll index 9ece86e66f923..fb234ff0014f4 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/basic-myriad.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/basic-myriad.ll @@ -1,6 +1,7 @@ ; Test basic address sanitizer instrumentation for Myriad. ; -; RUN: opt -asan -asan-module -S < %s | FileCheck %s +; RUN: opt -asan -asan-module -enable-new-pm=0 -S < %s | FileCheck %s +; RUN: opt -passes='asan-pipeline' -S < %s | FileCheck %s target triple = "sparc-myriad-rtems" target datalayout = "E-m:e-p:32:32-i64:64-f128:64-n32-S64" diff --git a/llvm/test/Instrumentation/AddressSanitizer/basic.ll b/llvm/test/Instrumentation/AddressSanitizer/basic.ll index 6397338344d6d..32462bb730c6a 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/basic.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/basic.ll @@ -1,11 +1,10 @@ ; Test basic address sanitizer instrumentation. ; -; RUN: opt < %s -asan -asan-module -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s -; RUN: opt < %s -asan -asan-module -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s +; RUN: opt < %s -asan -asan-module -S -enable-new-pm=0 | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -asan -asan-module -asan-mapping-scale=5 -S -enable-new-pm=0 | FileCheck --check-prefixes=CHECK,CHECK-S5 %s -; We need the requires since both asan and asan-module require reading module level metadata which is done once by the asan-globals-md analysis -; RUN: opt < %s -passes='require,function(asan),module(asan-module)' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s -; RUN: opt < %s -passes='require,function(asan),module(asan-module)' -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/byval-args.ll b/llvm/test/Instrumentation/AddressSanitizer/byval-args.ll index a070cedca37d9..e2d2464013a06 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/byval-args.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/byval-args.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-function-pipeline' -S | FileCheck %s ; Test that for call instructions, the by-value arguments are instrumented. target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug-info-alloca.ll b/llvm/test/Instrumentation/AddressSanitizer/debug-info-alloca.ll index 48cda7d7f48c2..2fe3790af558f 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/debug-info-alloca.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/debug-info-alloca.ll @@ -3,7 +3,8 @@ ; first instruction. Breaking on the instrumented function in a debugger ; would then stop at that instruction, before the prologue is finished. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s ; 1: void f(int *arg) { ; 2: } ; 3: int main(int argc, char **argv) { diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug-info-global-var.ll b/llvm/test/Instrumentation/AddressSanitizer/debug-info-global-var.ll index 959693e086fac..50bba89f88898 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/debug-info-global-var.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/debug-info-global-var.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s source_filename = "version.c" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.12.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll b/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll index c0389daddacd4..ce0126a08c19b 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/debug_info.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -asan-use-after-return=0 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return=0 -S | FileCheck %s ; Checks that llvm.dbg.declare instructions are updated ; accordingly as we merge allocas. diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca.ll b/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca.ll index 911ef6de32db1..745ef165ecb0a 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca.ll @@ -2,8 +2,10 @@ ; Only first-basic-block allocas are considered stack slots, and moving them ; breaks debug info. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-instrument-dynamic-allocas -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-instrument-dynamic-allocas -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-instrument-dynamic-allocas -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca2.ll b/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca2.ll index b6d393d0c33f0..69a4238342cd5 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca2.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/debug_info_noninstrumented_alloca2.ll @@ -1,7 +1,9 @@ ; Make sure we don't break the IR when moving non-instrumented allocas -; RUN: opt < %s -asan -asan-module -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-instrument-dynamic-allocas -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-instrument-dynamic-allocas -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-instrument-dynamic-allocas -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-globals-darwin.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-globals-darwin.ll index 7d15cd9537f17..3fc42e256b3bc 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-globals-darwin.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-globals-darwin.ll @@ -1,6 +1,7 @@ ; This test checks that we are not instrumenting unnecessary globals ; (llvm.metadata and other llvm internal globals). -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-globals-linux.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-globals-linux.ll index fc0e676ec1391..c946c6d4ac27d 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-globals-linux.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-globals-linux.ll @@ -1,6 +1,7 @@ ; This test checks that we are not instrumenting unnecessary globals ; (llvm.metadata, init_array sections, and other llvm internal globals). -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-internal-globals.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-internal-globals.ll index cff83ab718bbb..f93d3e2ff9223 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-internal-globals.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-internal-globals.ll @@ -1,6 +1,7 @@ ; This test checks that we are not instrumenting globals ; that we created ourselves. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-profiling-globals.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-profiling-globals.ll index f20977fc98831..2d0b952ece2d4 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-profiling-globals.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-profiling-globals.ll @@ -1,5 +1,6 @@ ; This test checks that we don't instrument globals created by profiling passes. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s @__profc_test = private global [1 x i64] zeroinitializer, section "__DATA,__llvm_prf_cnts", align 8 @__llvm_gcov_ctr = internal global [1 x i64] zeroinitializer diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-promotable-allocas.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-promotable-allocas.ll index 68913d321fe15..05b701731dff5 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-promotable-allocas.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-promotable-allocas.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -asan-instrument-dynamic-allocas -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-instrument-dynamic-allocas -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-instrument-dynamic-allocas -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-sanitizers.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-sanitizers.ll index b4407a8fc6df8..81b7ef7e0a37d 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-sanitizers.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-instrument-sanitizers.ll @@ -1,5 +1,6 @@ ; This test checks that we are not instrumenting sanitizer code. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-comdat-global.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-comdat-global.ll index 24141ee2190c7..545adcc0d7c0c 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-comdat-global.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-comdat-global.ll @@ -1,6 +1,7 @@ ; This test checks that we instrument regular globals, but do not touch ; the COMDAT ones. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32" target triple = "i686-pc-windows-msvc" ; no action should be taken for these globals diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-odr-global.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-odr-global.ll index bdcd6595a0f61..8379f634b2e13 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-odr-global.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-odr-global.ll @@ -1,6 +1,7 @@ ; This test checks that we instrument regular globals, but do not touch ; the linkonce_odr ones. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" ; no action should be taken for these globals diff --git a/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-threadlocal.ll b/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-threadlocal.ll index f863f44d51256..9b222452e1c5e 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-threadlocal.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/do-not-touch-threadlocal.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" ; no action should be taken for thread locals diff --git a/llvm/test/Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll b/llvm/test/Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll index 7d6b84144e9f8..0e6b2c45d5108 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/dynamic-shadow-darwin.ll @@ -1,17 +1,26 @@ ; Test using dynamic shadow address on darwin ; -; RUN: opt -asan -asan-module -mtriple=arm64_32-apple-watchos --data-layout="e-m:o-p:32:32-i64:64-i128:128-n32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 -; RUN: opt -asan -asan-module -mtriple=armv7k-apple-watchos --data-layout="e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 -; RUN: opt -asan -asan-module -mtriple=arm64-apple-ios --data-layout="e-m:o-i64:64-i128:128-n32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 -; RUN: opt -asan -asan-module -mtriple=armv7s-apple-ios --data-layout="e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 -; RUN: opt -asan -asan-module -mtriple=i386-apple-watchos-simulator --data-layout="e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 -; RUN: opt -asan -asan-module -mtriple=i386-apple-ios-simulator --data-layout="e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 -; RUN: opt -asan -asan-module -mtriple=x86_64-apple-ios-simulator --data-layout="e-m:o-i64:64-f80:128-n8:16:32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 +; RUN: opt -asan -asan-module -mtriple=arm64_32-apple-watchos --data-layout="e-m:o-p:32:32-i64:64-i128:128-n32:64-S128" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -passes='asan-pipeline' -mtriple=arm64_32-apple-watchos --data-layout="e-m:o-p:32:32-i64:64-i128:128-n32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -asan -asan-module -mtriple=armv7k-apple-watchos --data-layout="e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -passes='asan-pipeline' -mtriple=armv7k-apple-watchos --data-layout="e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -asan -asan-module -mtriple=arm64-apple-ios --data-layout="e-m:o-i64:64-i128:128-n32:64-S128" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 +; RUN: opt -passes='asan-pipeline' -mtriple=arm64-apple-ios --data-layout="e-m:o-i64:64-i128:128-n32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 +; RUN: opt -asan -asan-module -mtriple=armv7s-apple-ios --data-layout="e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -passes='asan-pipeline' -mtriple=armv7s-apple-ios --data-layout="e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -asan -asan-module -mtriple=i386-apple-watchos-simulator --data-layout="e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -passes='asan-pipeline' -mtriple=i386-apple-watchos-simulator --data-layout="e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -asan -asan-module -mtriple=i386-apple-ios-simulator --data-layout="e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -passes='asan-pipeline' -mtriple=i386-apple-ios-simulator --data-layout="e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=32 +; RUN: opt -asan -asan-module -mtriple=x86_64-apple-ios-simulator --data-layout="e-m:o-i64:64-f80:128-n8:16:32:64-S128" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 +; RUN: opt -passes='asan-pipeline' -mtriple=x86_64-apple-ios-simulator --data-layout="e-m:o-i64:64-f80:128-n8:16:32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 ; ; // macOS does not use dynamic shadow placement on x86_64 -; RUN: opt -asan -asan-module -mtriple=x86_64-apple-macosx --data-layout="e-m:o-i64:64-f80:128-n8:16:32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-NONDYNAMIC -DPTR_SIZE=64 +; RUN: opt -asan -asan-module -mtriple=x86_64-apple-macosx --data-layout="e-m:o-i64:64-f80:128-n8:16:32:64-S128" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-NONDYNAMIC -DPTR_SIZE=64 +; RUN: opt -passes='asan-pipeline' -mtriple=x86_64-apple-macosx --data-layout="e-m:o-i64:64-f80:128-n8:16:32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-NONDYNAMIC -DPTR_SIZE=64 ; // macOS does use dynamic shadow placement on arm64 -; RUN: opt -asan -asan-module -mtriple=arm64-apple-macosx --data-layout="e-m:o-i64:64-i128:128-n32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 +; RUN: opt -asan -asan-module -mtriple=arm64-apple-macosx --data-layout="e-m:o-i64:64-i128:128-n32:64-S128" -S < %s -enable-new-pm=0 | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 +; RUN: opt -passes='asan-pipeline' -mtriple=arm64-apple-macosx --data-layout="e-m:o-i64:64-i128:128-n32:64-S128" -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC -DPTR_SIZE=64 define i32 @test_load(i32* %a) sanitize_address { ; First instrumentation in the function must be to load the dynamic shadow diff --git a/llvm/test/Instrumentation/AddressSanitizer/experiment-call.ll b/llvm/test/Instrumentation/AddressSanitizer/experiment-call.ll index 0e339cc8041a3..4215d54574132 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/experiment-call.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/experiment-call.ll @@ -1,6 +1,7 @@ ; Test optimization experiments. ; -asan-force-experiment flag turns all memory accesses into experiments. -; RUN: opt < %s -asan -asan-module -asan-force-experiment=42 -asan-instrumentation-with-call-threshold=0 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-force-experiment=42 -asan-instrumentation-with-call-threshold=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-force-experiment=42 -asan-instrumentation-with-call-threshold=0 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/experiment.ll b/llvm/test/Instrumentation/AddressSanitizer/experiment.ll index aaa125f5d4086..274e0fdd136c3 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/experiment.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/experiment.ll @@ -1,6 +1,7 @@ ; Test optimization experiments. ; -asan-force-experiment flag turns all memory accesses into experiments. -; RUN: opt < %s -asan -asan-module -asan-force-experiment=42 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-force-experiment=42 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-force-experiment=42 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/force-dynamic-shadow.ll b/llvm/test/Instrumentation/AddressSanitizer/force-dynamic-shadow.ll index e364c23253f2f..70927ec2f0f75 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/force-dynamic-shadow.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/force-dynamic-shadow.ll @@ -1,7 +1,9 @@ ; Test -asan-force-dynamic-shadow flag. ; -; RUN: opt -asan -asan-module -S -asan-force-dynamic-shadow=1 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-FDS -; RUN: opt -asan -asan-module -S -asan-force-dynamic-shadow=0 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-NDS +; RUN: opt -asan -asan-module -enable-new-pm=0 -S -asan-force-dynamic-shadow=1 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-FDS +; RUN: opt -passes='asan-pipeline' -S -asan-force-dynamic-shadow=1 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-FDS +; RUN: opt -asan -asan-module -enable-new-pm=0 -S -asan-force-dynamic-shadow=0 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-NDS +; RUN: opt -passes='asan-pipeline' -S -asan-force-dynamic-shadow=0 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-NDS target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/freebsd.ll b/llvm/test/Instrumentation/AddressSanitizer/freebsd.ll index 3fbbfa3cb1ea6..b9ec93ee266e0 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/freebsd.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/freebsd.ll @@ -1,14 +1,29 @@ -; RUN: opt < %s -asan -asan-module -S \ +; RUN: opt < %s -asan -asan-module -S -enable-new-pm=0 \ ; RUN: -mtriple=i386-unknown-freebsd \ ; RUN: -data-layout="e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" | \ ; RUN: FileCheck --check-prefix=CHECK-32 %s -; RUN: opt < %s -asan -asan-module -S \ +; RUN: opt < %s -passes='asan-pipeline' -S \ +; RUN: -mtriple=i386-unknown-freebsd \ +; RUN: -data-layout="e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128" | \ +; RUN: FileCheck --check-prefix=CHECK-32 %s + +; RUN: opt < %s -asan -asan-module -S -enable-new-pm=0 \ +; RUN: -mtriple=x86_64-unknown-freebsd \ +; RUN: -data-layout="e-m:e-i64:64-f80:128-n8:16:32:64-S128" | \ +; RUN: FileCheck --check-prefix=CHECK-64 %s + +; RUN: opt < %s -passes='asan-pipeline' -S \ ; RUN: -mtriple=x86_64-unknown-freebsd \ ; RUN: -data-layout="e-m:e-i64:64-f80:128-n8:16:32:64-S128" | \ ; RUN: FileCheck --check-prefix=CHECK-64 %s -; RUN: opt < %s -asan -asan-module -S \ +; RUN: opt < %s -asan -asan-module -S -enable-new-pm=0 \ +; RUN: -mtriple=mips64-unknown-freebsd \ +; RUN: -data-layout="E-m:e-i64:64-n32:64-S128" | \ +; RUN: FileCheck --check-prefix=CHECK-MIPS64 %s + +; RUN: opt < %s -passes='asan-pipeline' -S \ ; RUN: -mtriple=mips64-unknown-freebsd \ ; RUN: -data-layout="E-m:e-i64:64-n32:64-S128" | \ ; RUN: FileCheck --check-prefix=CHECK-MIPS64 %s diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_addrspace.ll b/llvm/test/Instrumentation/AddressSanitizer/global_addrspace.ll index 19b76e6512511..fbc7ae1f09a78 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_addrspace.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_addrspace.ll @@ -1,7 +1,8 @@ ; Only verify that asan don't crash on global variables of different ; address space. The global variable should be unmodified by asan. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_cstring_darwin.ll b/llvm/test/Instrumentation/AddressSanitizer/global_cstring_darwin.ll index 0fc3205ba492c..71d83eccb334f 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_cstring_darwin.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_cstring_darwin.ll @@ -1,5 +1,6 @@ ; This test checks that instrumented global C (null terminated) strings are put into a special section on Darwin. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.10.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll b/llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll index aa02553f4416a..304dfb6d0496e 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_lto_merge.ll @@ -1,5 +1,7 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -constmerge -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -constmerge -S | FileCheck %s +; RUN: opt < %s "-passes=asan-pipeline,constmerge" -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll index ea9f2cf3f1a9d..25033599b62d6 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata.ll @@ -1,5 +1,7 @@ -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=1 -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=1 -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=1 -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=1 -asan-mapping-scale=5 -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll index b1a600f3ceb8d..f5b9e4c2408dd 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_array.ll @@ -1,7 +1,11 @@ -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=0 -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=0 -mtriple=x86_64-apple-macosx10.11.0 -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=0 -mtriple=x86_64-pc-windows-msvc19.0.24215 -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=0 -asan-mapping-scale=5 -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=0 -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=0 -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=0 -mtriple=x86_64-apple-macosx10.11.0 -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=0 -mtriple=x86_64-apple-macosx10.11.0 -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=0 -mtriple=x86_64-pc-windows-msvc19.0.24215 -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=0 -mtriple=x86_64-pc-windows-msvc19.0.24215 -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=0 -asan-mapping-scale=5 -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=0 -asan-mapping-scale=5 -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_bitcasts.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_bitcasts.ll index 324a04e3b8321..3b4c8444feaf0 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_bitcasts.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_bitcasts.ll @@ -1,7 +1,8 @@ ; Test that the compiler doesn't crash when the llvm.asan.globals containts ; an entry that points to a BitCast instruction. -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=1 -S +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=1 -S +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=1 -S target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll index 1723b33636226..2790ff6fc7499 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_darwin.ll @@ -2,7 +2,8 @@ ; allowing dead stripping to be performed, and that the appropriate runtime ; routines are invoked. -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=1 -S | FileCheck %s target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-apple-macosx10.11.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_external_comdat.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_external_comdat.ll index 29725adcd039a..30f2f12f33512 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_external_comdat.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_external_comdat.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -mtriple=x86_64-linux -asan -asan-module -asan-globals-live-support=0 -S | FileCheck %s +; RUN: opt < %s -mtriple=x86_64-linux -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=0 -S | FileCheck %s +; RUN: opt < %s -mtriple=x86_64-linux -passes='asan-pipeline' -asan-globals-live-support=0 -S | FileCheck %s $my_var = comdat any diff --git a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll index 744366e4c3766..628f32df36219 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/global_metadata_windows.ll @@ -4,7 +4,8 @@ ; FIXME: Later we can use this to instrument linkonce odr string literals. -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=1 -S | FileCheck %s target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc19.0.24215" diff --git a/llvm/test/Instrumentation/AddressSanitizer/hoist-argument-init-insts.ll b/llvm/test/Instrumentation/AddressSanitizer/hoist-argument-init-insts.ll index 1414b2122d983..821bfc86a0e5b 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/hoist-argument-init-insts.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/hoist-argument-init-insts.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -asan-use-after-return -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return -S | FileCheck %s ; Source (-O0 -fsanitize=address -fsanitize-address-use-after-scope): ;; struct S { int x, y; }; diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll index 6fc52bb66ded4..434e4be4e8e6d 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll @@ -1,7 +1,8 @@ ; Test asan internal compiler flags: ; -asan-instrument-dynamic-allocas -; RUN: opt < %s -asan -asan-module -asan-instrument-dynamic-allocas -S | FileCheck %s --check-prefix=CHECK-ALLOCA +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-instrument-dynamic-allocas -S | FileCheck %s --check-prefix=CHECK-ALLOCA +; RUN: opt < %s -passes='asan-pipeline' -asan-instrument-dynamic-allocas -S | FileCheck %s --check-prefix=CHECK-ALLOCA target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument-no-return.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument-no-return.ll index 22ee66301de25..b255a15411ed1 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument-no-return.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument-no-return.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-function-pipeline' -S | FileCheck %s ; AddressSanitizer must insert __asan_handle_no_return ; before noreturn calls that aren't inserted by sanitizers. diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument-stack.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument-stack.ll index f33481112f872..e563f702749b8 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument-stack.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument-stack.ll @@ -1,6 +1,8 @@ ; This test checks that we are not instrumenting direct inbound stack accesses. -; RUN: opt < %s -asan -asan-module -asan-opt-stack -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-opt-stack -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-opt-stack -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-opt-stack -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-opt-stack -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-opt-stack -asan-mapping-scale=5 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll index 5631572d93da2..18c40a503b5c5 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_global.ll @@ -1,5 +1,7 @@ -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=1 -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-globals-live-support=1 -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-globals-live-support=1 -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-globals-live-support=1 -asan-mapping-scale=5 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" @xxx = global i32 0, align 4 diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll index d392662efc711..ae043dc0c2c59 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_initializer_metadata.ll @@ -1,5 +1,7 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-scale=5 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" @xxx = internal global i32 0, align 4 ; With dynamic initializer. diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrument_load_then_store.ll b/llvm/test/Instrumentation/AddressSanitizer/instrument_load_then_store.ll index 8341697ff48c9..ea350dab4e3b8 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrument_load_then_store.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrument_load_then_store.ll @@ -1,6 +1,8 @@ ; Test that AddressSanitizer instruments "(*a)++" only once. -; RUN: opt < %s -asan -asan-module -S -asan-opt=1 | FileCheck %s -check-prefix=OPT1 -; RUN: opt < %s -asan -asan-module -S -asan-opt=0 | FileCheck %s -check-prefix=OPT0 +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S -asan-opt=1 | FileCheck %s -check-prefix=OPT1 +; RUN: opt < %s -passes='asan-pipeline' -S -asan-opt=1 | FileCheck %s -check-prefix=OPT1 +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S -asan-opt=0 | FileCheck %s -check-prefix=OPT0 +; RUN: opt < %s -passes='asan-pipeline' -S -asan-opt=0 | FileCheck %s -check-prefix=OPT0 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/instrumentation-with-call-threshold.ll b/llvm/test/Instrumentation/AddressSanitizer/instrumentation-with-call-threshold.ll index 8e0275d2c17de..82a61aabea4d9 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/instrumentation-with-call-threshold.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/instrumentation-with-call-threshold.ll @@ -2,11 +2,16 @@ ; -asan-instrumentation-with-call-threshold ; -asan-memory-access-callback-prefix -; RUN: opt < %s -asan -asan-module -asan-instrumentation-with-call-threshold=1 -S | FileCheck %s --check-prefix=CHECK-CALL -; RUN: opt < %s -asan -asan-module -asan-instrumentation-with-call-threshold=0 -S | FileCheck %s --check-prefix=CHECK-CALL -; RUN: opt < %s -asan -asan-module -asan-instrumentation-with-call-threshold=0 -asan-memory-access-callback-prefix=__foo_ -S | FileCheck %s --check-prefix=CHECK-CUSTOM-PREFIX -; RUN: opt < %s -asan -asan-module -asan-instrumentation-with-call-threshold=5 -S | FileCheck %s --check-prefix=CHECK-INLINE -; RUN: opt < %s -asan -asan-module -S | FileCheck %s --check-prefix=CHECK-INLINE +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-instrumentation-with-call-threshold=1 -S | FileCheck %s --check-prefix=CHECK-CALL +; RUN: opt < %s -passes='asan-pipeline' -asan-instrumentation-with-call-threshold=1 -S | FileCheck %s --check-prefix=CHECK-CALL +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-instrumentation-with-call-threshold=0 -S | FileCheck %s --check-prefix=CHECK-CALL +; RUN: opt < %s -passes='asan-pipeline' -asan-instrumentation-with-call-threshold=0 -S | FileCheck %s --check-prefix=CHECK-CALL +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-instrumentation-with-call-threshold=0 -asan-memory-access-callback-prefix=__foo_ -S | FileCheck %s --check-prefix=CHECK-CUSTOM-PREFIX +; RUN: opt < %s -passes='asan-pipeline' -asan-instrumentation-with-call-threshold=0 -asan-memory-access-callback-prefix=__foo_ -S | FileCheck %s --check-prefix=CHECK-CUSTOM-PREFIX +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-instrumentation-with-call-threshold=5 -S | FileCheck %s --check-prefix=CHECK-INLINE +; RUN: opt < %s -passes='asan-pipeline' -asan-instrumentation-with-call-threshold=5 -S | FileCheck %s --check-prefix=CHECK-INLINE +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s --check-prefix=CHECK-INLINE +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s --check-prefix=CHECK-INLINE target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/keep_going.ll b/llvm/test/Instrumentation/AddressSanitizer/keep_going.ll index 4bb59e74e8f14..7a3fbc39ff271 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/keep_going.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/keep_going.ll @@ -1,7 +1,8 @@ ; Test asan internal compiler flags: ; -asan-recover=1 -; RUN: opt < %s -asan -asan-recover -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -asan-recover -asan-module -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-recover -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/lifetime-throw.ll b/llvm/test/Instrumentation/AddressSanitizer/lifetime-throw.ll index ff03d10c7c5d7..64473fb59f76e 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/lifetime-throw.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/lifetime-throw.ll @@ -1,5 +1,6 @@ ; Test handling of llvm.lifetime intrinsics with C++ exceptions. -; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/lifetime-uar-uas.ll b/llvm/test/Instrumentation/AddressSanitizer/lifetime-uar-uas.ll index 437b6a94185b8..136a8457fcf19 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/lifetime-uar-uas.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/lifetime-uar-uas.ll @@ -1,8 +1,12 @@ ; Test handling of llvm.lifetime intrinsics in UAR/UAS modes. -; RUN: opt < %s -asan -asan-module -asan-use-after-return=0 -asan-use-after-scope=0 -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-use-after-return=1 -asan-use-after-scope=0 -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-use-after-return=0 -asan-use-after-scope=1 -S | FileCheck %s --check-prefix=CHECK-UAS -; RUN: opt < %s -asan -asan-module -asan-use-after-return=1 -asan-use-after-scope=1 -S | FileCheck %s --check-prefix=CHECK-UAS +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return=0 -asan-use-after-scope=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return=0 -asan-use-after-scope=0 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return=1 -asan-use-after-scope=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return=1 -asan-use-after-scope=0 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return=0 -asan-use-after-scope=1 -S | FileCheck %s --check-prefix=CHECK-UAS +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return=0 -asan-use-after-scope=1 -S | FileCheck %s --check-prefix=CHECK-UAS +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return=1 -asan-use-after-scope=1 -S | FileCheck %s --check-prefix=CHECK-UAS +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return=1 -asan-use-after-scope=1 -S | FileCheck %s --check-prefix=CHECK-UAS target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" diff --git a/llvm/test/Instrumentation/AddressSanitizer/lifetime.ll b/llvm/test/Instrumentation/AddressSanitizer/lifetime.ll index b951afdc670f1..26aa65715d262 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/lifetime.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/lifetime.ll @@ -1,6 +1,8 @@ ; Test handling of llvm.lifetime intrinsics. -; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT -; RUN: opt < %s -asan -asan-module -asan-use-after-scope -asan-use-after-return=0 -asan-instrument-dynamic-allocas=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-NO-DYNAMIC +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-scope -asan-use-after-return=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-DEFAULT +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-scope -asan-use-after-return=0 -asan-instrument-dynamic-allocas=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-NO-DYNAMIC +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-scope -asan-use-after-return=0 -asan-instrument-dynamic-allocas=0 -S | FileCheck %s --check-prefixes=CHECK,CHECK-NO-DYNAMIC target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/local_alias.ll b/llvm/test/Instrumentation/AddressSanitizer/local_alias.ll index 9b95bb3fa6b04..a4c5803fc8189 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/local_alias.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/local_alias.ll @@ -1,7 +1,11 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s --check-prefixes=CHECK-NOALIAS,CHECK-NOINDICATOR -; RUN: opt < %s -asan -asan-module -asan-use-private-alias=1 -S | FileCheck %s --check-prefixes=CHECK-ALIAS,CHECK-NOINDICATOR -; RUN: opt < %s -asan -asan-module -asan-use-odr-indicator=1 -S | FileCheck %s --check-prefixes=CHECK-INDICATOR,CHECK-NOALIAS -; RUN: opt < %s -asan -asan-module -asan-use-private-alias=1 -asan-use-odr-indicator=1 -S | FileCheck %s --check-prefixes=CHECK-ALIAS,CHECK-INDICATOR +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s --check-prefixes=CHECK-NOALIAS,CHECK-NOINDICATOR +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s --check-prefixes=CHECK-NOALIAS,CHECK-NOINDICATOR +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-private-alias=1 -S | FileCheck %s --check-prefixes=CHECK-ALIAS,CHECK-NOINDICATOR +; RUN: opt < %s -passes='asan-pipeline' -asan-use-private-alias=1 -S | FileCheck %s --check-prefixes=CHECK-ALIAS,CHECK-NOINDICATOR +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-odr-indicator=1 -S | FileCheck %s --check-prefixes=CHECK-INDICATOR,CHECK-NOALIAS +; RUN: opt < %s -passes='asan-pipeline' -asan-use-odr-indicator=1 -S | FileCheck %s --check-prefixes=CHECK-INDICATOR,CHECK-NOALIAS +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-private-alias=1 -asan-use-odr-indicator=1 -S | FileCheck %s --check-prefixes=CHECK-ALIAS,CHECK-INDICATOR +; RUN: opt < %s -passes='asan-pipeline' -asan-use-private-alias=1 -asan-use-odr-indicator=1 -S | FileCheck %s --check-prefixes=CHECK-ALIAS,CHECK-INDICATOR target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll b/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll index 7bf294cb6b600..c9dec38d227bc 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/local_stack_base.ll @@ -1,4 +1,5 @@ -; RUN: opt -S -asan -asan-skip-promotable-allocas=0 %s -o - | FileCheck %s +; RUN: opt -S -asan -enable-new-pm=0 -asan-skip-promotable-allocas=0 %s -o - | FileCheck %s +; RUN: opt -S -passes='asan-function-pipeline' -asan-skip-promotable-allocas=0 %s -o - | FileCheck %s ; Generated from: ; int bar(int y) { ; return y + 2; diff --git a/llvm/test/Instrumentation/AddressSanitizer/localescape.ll b/llvm/test/Instrumentation/AddressSanitizer/localescape.ll index 015b0e84ff16c..8daeb2927f935 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/localescape.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/localescape.ll @@ -1,5 +1,7 @@ -; RUN: opt < %s -asan -asan-module -asan-use-after-return -asan-stack-dynamic-alloca -S | FileCheck %s -; RUN: opt < %s -asan -asan-module -asan-use-after-return=0 -asan-stack-dynamic-alloca=0 -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return -asan-stack-dynamic-alloca -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return -asan-stack-dynamic-alloca -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return=0 -asan-stack-dynamic-alloca=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return=0 -asan-stack-dynamic-alloca=0 -S | FileCheck %s target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "i686-pc-windows-msvc18.0.0" diff --git a/llvm/test/Instrumentation/AddressSanitizer/no-globals.ll b/llvm/test/Instrumentation/AddressSanitizer/no-globals.ll index 30388b1865eb5..ea84ac387a71f 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/no-globals.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/no-globals.ll @@ -1,5 +1,6 @@ ; A module with no asan-instrumented globals has no asan destructor, and has an asan constructor in a comdat. -; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -asan -asan-module -asan-with-comdat=1 -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -asan -asan-module -enable-new-pm=0 -asan-with-comdat=1 -asan-globals-live-support=1 -S | FileCheck %s +; RUN: opt -mtriple=x86_64-unknown-linux-gnu < %s -passes='asan-pipeline' -asan-with-comdat=1 -asan-globals-live-support=1 -S | FileCheck %s define void @f() { ret void diff --git a/llvm/test/Instrumentation/AddressSanitizer/odr-check-ignore.ll b/llvm/test/Instrumentation/AddressSanitizer/odr-check-ignore.ll index cf48d19c16c2d..09b3d2f519297 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/odr-check-ignore.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/odr-check-ignore.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/ps4.ll b/llvm/test/Instrumentation/AddressSanitizer/ps4.ll index e160996866b4f..5930e31a4dd79 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/ps4.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/ps4.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -S -mtriple=x86_64-scei-ps4 | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S -mtriple=x86_64-scei-ps4 | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S -mtriple=x86_64-scei-ps4 | FileCheck %s define i32 @read_4_bytes(i32* %a) sanitize_address { entry: diff --git a/llvm/test/Instrumentation/AddressSanitizer/scale-offset.ll b/llvm/test/Instrumentation/AddressSanitizer/scale-offset.ll index 8345586fec4e8..f0b8fb8fc8374 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/scale-offset.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/scale-offset.ll @@ -1,8 +1,11 @@ ; Test that the scale (-asan-mapping-scale) and offset (-asan-mapping-offset) command-line options work as expected ; -; RUN: opt < %s -asan -asan-module -asan-mapping-offset 0xdeadbeef -S | FileCheck --check-prefix=CHECK-OFFSET %s -; RUN: opt < %s -asan -asan-module -asan-mapping-scale 1 -S | FileCheck --check-prefix=CHECK-SCALE %s -; RUN: opt < %s -asan -asan-module -asan-mapping-offset 0xc0ffee -asan-mapping-scale 0 -S | FileCheck --check-prefix=CHECK-BOTH %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-mapping-offset 0xdeadbeef -S | FileCheck --check-prefix=CHECK-OFFSET %s +; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-offset 0xdeadbeef -S | FileCheck --check-prefix=CHECK-OFFSET %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-mapping-scale 1 -S | FileCheck --check-prefix=CHECK-SCALE %s +; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-scale 1 -S | FileCheck --check-prefix=CHECK-SCALE %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-mapping-offset 0xc0ffee -asan-mapping-scale 0 -S | FileCheck --check-prefix=CHECK-BOTH %s +; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-offset 0xc0ffee -asan-mapping-scale 0 -S | FileCheck --check-prefix=CHECK-BOTH %s target triple = "x86_64-unknown-linux-gnu" define i32 @read_offset(i32* %a) sanitize_address { diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime-be.ll b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime-be.ll index 2261094275123..a9181fc4c3de9 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime-be.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime-be.ll @@ -1,8 +1,10 @@ ; Regular stack poisoning. -; RUN: opt < %s -asan -asan-module -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,EXIT %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,EXIT %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,EXIT %s ; Stack poisoning with stack-use-after-scope. -; RUN: opt < %s -asan -asan-module -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS,EXIT-UAS %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS,EXIT-UAS %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS,EXIT-UAS %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll index 5523da63d373b..54128bb0c9e4c 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-and-lifetime.ll @@ -1,8 +1,10 @@ ; Regular stack poisoning. -; RUN: opt < %s -asan -asan-module -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,EXIT %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,EXIT %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-scope=0 -S | FileCheck --check-prefixes=CHECK,ENTRY,EXIT %s ; Stack poisoning with stack-use-after-scope. -; RUN: opt < %s -asan -asan-module -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS,EXIT-UAS %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS,EXIT-UAS %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-scope=1 -S | FileCheck --check-prefixes=CHECK,ENTRY-UAS,EXIT-UAS %s target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll index 859404b12de2e..616c18ea09d60 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning-byval-args.ll @@ -1,8 +1,12 @@ ; This check verifies that arguments passed by value get redzones. -; RUN: opt < %s -asan -asan-realign-stack=32 -S | FileCheck %s -; RUN: opt < %s -asan -asan-realign-stack=32 -asan-force-dynamic-shadow -S | FileCheck %s -; RUN: opt < %s -asan -asan-realign-stack=32 -asan-mapping-scale=5 -S | FileCheck %s -; RUN: opt < %s -asan -asan-realign-stack=32 -asan-force-dynamic-shadow -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -asan-realign-stack=32 -S | FileCheck %s +; RUN: opt < %s -passes='asan-function-pipeline' -asan-realign-stack=32 -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -asan-realign-stack=32 -asan-force-dynamic-shadow -S | FileCheck %s +; RUN: opt < %s -passes='asan-function-pipeline' -asan-realign-stack=32 -asan-force-dynamic-shadow -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -asan-realign-stack=32 -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -passes='asan-function-pipeline' -asan-realign-stack=32 -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -asan-realign-stack=32 -asan-force-dynamic-shadow -asan-mapping-scale=5 -S | FileCheck %s +; RUN: opt < %s -passes='asan-function-pipeline' -asan-realign-stack=32 -asan-force-dynamic-shadow -asan-mapping-scale=5 -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning.ll b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning.ll index 4e5c2958ddb8f..0505f9a1e0920 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/stack-poisoning.ll @@ -1,5 +1,7 @@ -; RUN: opt < %s -asan -asan-module -asan-use-after-return -S | FileCheck --check-prefix=CHECK-UAR %s -; RUN: opt < %s -asan -asan-module -asan-use-after-return=0 -S | FileCheck --check-prefix=CHECK-PLAIN %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return -S | FileCheck --check-prefix=CHECK-UAR %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return -S | FileCheck --check-prefix=CHECK-UAR %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-use-after-return=0 -S | FileCheck --check-prefix=CHECK-PLAIN %s +; RUN: opt < %s -passes='asan-pipeline' -asan-use-after-return=0 -S | FileCheck --check-prefix=CHECK-PLAIN %s target datalayout = "e-i64:64-f80:128-s:64-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll b/llvm/test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll index 90ddd7786b9bf..6140ba6b7a80e 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll @@ -1,6 +1,10 @@ ; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca \ +; RUN: -asan-use-after-return -S -enable-new-pm=0 | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-stack-dynamic-alloca \ ; RUN: -asan-use-after-return -S | FileCheck %s ; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca -asan-mapping-scale=5 \ +; RUN: -asan-use-after-return -S -enable-new-pm=0 | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -asan-stack-dynamic-alloca -asan-mapping-scale=5 \ ; RUN: -asan-use-after-return -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll b/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll index 85169d523b685..58b6714c90533 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/stack_layout.ll @@ -1,8 +1,12 @@ ; Test the ASan's stack layout. ; More tests in tests/Transforms/Utils/ASanStackFrameLayoutTest.cpp -; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca=0 -asan-use-after-scope -S \ +; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca=0 -asan-use-after-scope -S -enable-new-pm=0 \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-STATIC -; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca=1 -asan-use-after-scope -S \ +; RUN: opt < %s -passes='asan-pipeline' -asan-stack-dynamic-alloca=0 -asan-use-after-scope -S \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-STATIC +; RUN: opt < %s -asan -asan-module -asan-stack-dynamic-alloca=1 -asan-use-after-scope -S -enable-new-pm=0 \ +; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC +; RUN: opt < %s -passes='asan-pipeline' -asan-stack-dynamic-alloca=1 -asan-use-after-scope -S \ ; RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-DYNAMIC target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" diff --git a/llvm/test/Instrumentation/AddressSanitizer/str-nobuiltin.ll b/llvm/test/Instrumentation/AddressSanitizer/str-nobuiltin.ll index dd0132d435bd2..446e7f6793ba6 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/str-nobuiltin.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/str-nobuiltin.ll @@ -1,6 +1,7 @@ ; Test marking string functions as nobuiltin in address sanitizer. ; -; RUN: opt < %s -asan -S | FileCheck %s +; RUN: opt < %s -asan -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-function-pipeline' -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/test64.ll b/llvm/test/Instrumentation/AddressSanitizer/test64.ll index 4aab5310635fd..c6b190c861a1e 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/test64.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/test64.ll @@ -1,5 +1,7 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s -; RUN: opt < %s -asan -asan-module -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck --check-prefixes=CHECK,CHECK-S3 %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s +; RUN: opt < %s -passes='asan-pipeline' -asan-mapping-scale=5 -S | FileCheck --check-prefixes=CHECK,CHECK-S5 %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" define i32 @read_4_bytes(i32* %a) sanitize_address { diff --git a/llvm/test/Instrumentation/AddressSanitizer/twice.ll b/llvm/test/Instrumentation/AddressSanitizer/twice.ll index 9f7826f739521..4b5b64080dd29 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/twice.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/twice.ll @@ -1,5 +1,6 @@ ; Check that the address sanitizer pass can be reused -; RUN: opt < %s -S -run-twice -asan +; RUN: opt < %s -S -run-twice -asan -enable-new-pm=0 +; RUN: opt < %s -S -run-twice -passes='asan-function-pipeline' define void @foo(i64* %b) nounwind uwtable sanitize_address { entry: diff --git a/llvm/test/Instrumentation/AddressSanitizer/ubsan.ll b/llvm/test/Instrumentation/AddressSanitizer/ubsan.ll index 23b7ef4537c4f..41fab72ddbea9 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/ubsan.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/ubsan.ll @@ -1,6 +1,7 @@ ; ASan shouldn't instrument code added by UBSan. -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Instrumentation/AddressSanitizer/win-sorted-sections.ll b/llvm/test/Instrumentation/AddressSanitizer/win-sorted-sections.ll index 85f759cf740c1..a384186255f02 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/win-sorted-sections.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/win-sorted-sections.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s ; All of these globals should pass through uninstrumented because of their ; custom section name. The .CRT section is the standard way to register custom diff --git a/llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll b/llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll index 4d5126be87c60..3eb98508fec6b 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/win-string-literal.ll @@ -1,4 +1,5 @@ -; RUN: opt < %s -asan -asan-module -S | FileCheck %s +; RUN: opt < %s -asan -asan-module -enable-new-pm=0 -S | FileCheck %s +; RUN: opt < %s -passes='asan-pipeline' -S | FileCheck %s ; Generated like so: ; $ clang -S -emit-llvm -Xclang -disable-llvm-passes -fsanitize=address -O1 t.cpp -o t.ll diff --git a/llvm/test/Instrumentation/AddressSanitizer/with-ifunc.ll b/llvm/test/Instrumentation/AddressSanitizer/with-ifunc.ll index 4771a9674017b..ed5df2a2dfb05 100644 --- a/llvm/test/Instrumentation/AddressSanitizer/with-ifunc.ll +++ b/llvm/test/Instrumentation/AddressSanitizer/with-ifunc.ll @@ -1,18 +1,30 @@ ; Test -asan-with-ifunc flag. ; -; RUN: opt -asan -asan-module -S -asan-with-ifunc=0 < %s | \ +; RUN: opt -asan -asan-module -S -asan-with-ifunc=0 < %s -enable-new-pm=0 | \ ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOIFUNC -; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 < %s | \ +; RUN: opt -passes='asan-pipeline' -S -asan-with-ifunc=0 < %s | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOIFUNC +; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 < %s -enable-new-pm=0 | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC +; RUN: opt -passes='asan-pipeline' -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 < %s | \ ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC -; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=1 < %s | \ +; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=1 < %s -enable-new-pm=0 | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC-NOREMAT +; RUN: opt -passes='asan-pipeline' -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=1 < %s | \ ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC-NOREMAT ; Pre-Lollipop Android does not support ifunc. -; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android20 < %s | \ +; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android20 < %s -enable-new-pm=0 | \ ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOIFUNC -; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android < %s | \ +; RUN: opt -passes='asan-pipeline' -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android20 < %s | \ ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOIFUNC -; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android21 < %s | \ +; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android < %s -enable-new-pm=0 | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOIFUNC +; RUN: opt -passes='asan-pipeline' -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android < %s | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-NOIFUNC +; RUN: opt -asan -asan-module -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android21 < %s -enable-new-pm=0 | \ +; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC +; RUN: opt -passes='asan-pipeline' -S -asan-with-ifunc=1 -asan-with-ifunc-suppress-remat=0 -mtriple=armv7-linux-android21 < %s | \ ; RUN: FileCheck %s --check-prefixes=CHECK,CHECK-IFUNC target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64" diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp index b94c58decdda2..47c9cfc65e7ba 100644 --- a/llvm/tools/opt/NewPMDriver.cpp +++ b/llvm/tools/opt/NewPMDriver.cpp @@ -34,6 +34,7 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" +#include "llvm/Transforms/Instrumentation/AddressSanitizer.h" #include "llvm/Transforms/Scalar/LoopPassManager.h" #include "llvm/Transforms/Utils/Debugify.h" @@ -297,6 +298,25 @@ bool llvm::runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM, } return false; }); + PB.registerPipelineParsingCallback( + [](StringRef Name, ModulePassManager &MPM, + ArrayRef) { + if (Name == "asan-pipeline") { + MPM.addPass( + RequireAnalysisPass()); + MPM.addPass( + createModuleToFunctionPassAdaptor(AddressSanitizerPass())); + MPM.addPass(ModuleAddressSanitizerPass()); + return true; + } else if (Name == "asan-function-pipeline") { + MPM.addPass( + RequireAnalysisPass()); + MPM.addPass( + createModuleToFunctionPassAdaptor(AddressSanitizerPass())); + return true; + } + return false; + }); #define HANDLE_EXTENSION(Ext) \ get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB); From c12f11184682c55e10922665cea628332eb158eb Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 17 Jul 2020 18:29:47 -0700 Subject: [PATCH 699/771] Corrected __libfuzzer_is_present symbol inclusion for MSVC x86 32-bit The incorrect symbol will cause linking failures for 32-bit targets: clang_rt.fuzzer-i386.lib(FuzzerDriver.obj) : error LNK2001: unresolved external symbol __libfuzzer_is_present Verified no longer fails to link with this change for 32-bit and still succeeds for 64-bit MSVC. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D83594 --- compiler-rt/lib/fuzzer/FuzzerDriver.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp index a847c76e292d7..00a33a413d2f3 100644 --- a/compiler-rt/lib/fuzzer/FuzzerDriver.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerDriver.cpp @@ -33,7 +33,11 @@ // binary can test for its existence. #if LIBFUZZER_MSVC extern "C" void __libfuzzer_is_present() {} +#if defined(_M_IX86) || defined(__i386__) +#pragma comment(linker, "/include:___libfuzzer_is_present") +#else #pragma comment(linker, "/include:__libfuzzer_is_present") +#endif #else extern "C" __attribute__((used)) void __libfuzzer_is_present() {} #endif // LIBFUZZER_MSVC From cbf64b58345dd9c1f0032c4fce558ed2f1fd0fe4 Mon Sep 17 00:00:00 2001 From: "Joel E. Denny" Date: Fri, 17 Jul 2020 21:35:21 -0400 Subject: [PATCH 700/771] [OpenMP] Fix map clause for unused var: don't ignore it For example, without this patch: ``` $ cat test.c int main() { int x[3]; #pragma omp target map(tofrom:x[0:3]) #ifdef USE x[0] = 1 #endif ; return 0; } $ clang -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda -S -emit-llvm test.c $ grep '^@.offload_maptypes' test.ll $ echo $? 1 $ clang -fopenmp -fopenmp-targets=nvptx64-nvidia-cuda -S -emit-llvm test.c \ -DUSE $ grep '^@.offload_maptypes' test.ll @.offload_maptypes = private unnamed_addr constant [1 x i64] [i64 35] ``` With this patch, both greps produce the same result. Reviewed By: ABataev Differential Revision: https://reviews.llvm.org/D83922 --- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 63 +- clang/test/OpenMP/target_map_codegen.cpp | 1175 +++++++++++------ .../test/OpenMP/target_teams_map_codegen.cpp | 13 +- 3 files changed, 789 insertions(+), 462 deletions(-) diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 89f403f2c82f4..f6d36bd84385f 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -7977,7 +7977,10 @@ class MappableExprsHandler { /// CombinedInfo). Also, for each item that relates with a device pointer, a /// pair of the relevant declaration and index where it occurs is appended to /// the device pointers info array. - void generateAllInfo(MapCombinedInfoTy &CombinedInfo) const { + void generateAllInfo( + MapCombinedInfoTy &CombinedInfo, + const llvm::DenseSet> &SkipVarSet = + llvm::DenseSet>()) const { // We have to process the component lists that relate with the same // declaration in a single chunk so that we can generate the map flags // correctly. Therefore, we organize all lists in a map. @@ -7986,14 +7989,17 @@ class MappableExprsHandler { // Helper function to fill the information map for the different supported // clauses. auto &&InfoGen = - [&Info](const ValueDecl *D, - OMPClauseMappableExprCommon::MappableExprComponentListRef L, - OpenMPMapClauseKind MapType, - ArrayRef MapModifiers, - bool ReturnDevicePointer, bool IsImplicit, - const ValueDecl *Mapper, bool ForDeviceAddr = false) { + [&Info, &SkipVarSet]( + const ValueDecl *D, + OMPClauseMappableExprCommon::MappableExprComponentListRef L, + OpenMPMapClauseKind MapType, + ArrayRef MapModifiers, + bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper, + bool ForDeviceAddr = false) { const ValueDecl *VD = D ? cast(D->getCanonicalDecl()) : nullptr; + if (SkipVarSet.count(VD)) + return; Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, IsImplicit, Mapper, ForDeviceAddr); }; @@ -8561,38 +8567,6 @@ class MappableExprsHandler { } } - /// Generate the base pointers, section pointers, sizes, map types, and - /// mappers associated with the declare target link variables (all included in - /// \a CombinedInfo). - void generateInfoForDeclareTargetLink(MapCombinedInfoTy &CombinedInfo) const { - assert(CurDir.is() && - "Expect a executable directive"); - const auto *CurExecDir = CurDir.get(); - // Map other list items in the map clause which are not captured variables - // but "declare target link" global variables. - for (const auto *C : CurExecDir->getClausesOfKind()) { - for (const auto L : C->component_lists()) { - if (!std::get<0>(L)) - continue; - const auto *VD = dyn_cast_or_null(std::get<0>(L)); - if (!VD) - continue; - llvm::Optional Res = - OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || - !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) - continue; - StructRangeInfoTy PartialStruct; - generateInfoForComponentList( - C->getMapType(), C->getMapTypeModifiers(), std::get<1>(L), - CombinedInfo, PartialStruct, /*IsFirstComponentList=*/true, - C->isImplicit()); - assert(!PartialStruct.Base.isValid() && - "No partial structs for declare target link expected."); - } - } - } - /// Generate the default map information for a given capture \a CI, /// record field declaration \a RI and captured value \a CV. void generateDefaultMapInfo(const CapturedStmt::Capture &CI, @@ -9521,6 +9495,7 @@ void CGOpenMPRuntime::emitTargetCall( // Get mappable expression information. MappableExprsHandler MEHandler(D, CGF); llvm::DenseMap LambdaPointers; + llvm::DenseSet> MappedVarSet; auto RI = CS.getCapturedRecordDecl()->field_begin(); auto CV = CapturedVars.begin(); @@ -9546,6 +9521,10 @@ void CGOpenMPRuntime::emitTargetCall( // If we have any information in the map clause, we use it, otherwise we // just do a default mapping. MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct); + if (!CI->capturesThis()) + MappedVarSet.insert(CI->getCapturedVar()); + else + MappedVarSet.insert(nullptr); if (CurInfo.BasePointers.empty()) MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo); // Generate correct mapping for variables captured by reference in @@ -9575,9 +9554,9 @@ void CGOpenMPRuntime::emitTargetCall( MEHandler.adjustMemberOfForLambdaCaptures( LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, CombinedInfo.Types); - // Map other list items in the map clause which are not captured variables - // but "declare target link" global variables. - MEHandler.generateInfoForDeclareTargetLink(CombinedInfo); + // Map any list items in a map clause that were not captures because they + // weren't referenced within the construct. + MEHandler.generateAllInfo(CombinedInfo, MappedVarSet); TargetDataInfo Info; // Fill up the arrays and create the arguments. diff --git a/clang/test/OpenMP/target_map_codegen.cpp b/clang/test/OpenMP/target_map_codegen.cpp index 69d0fc3c5f30c..2eab004eeff2e 100644 --- a/clang/test/OpenMP/target_map_codegen.cpp +++ b/clang/test/OpenMP/target_map_codegen.cpp @@ -1307,12 +1307,26 @@ void implicit_maps_template_type_capture (int a){ #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-64 +// RUN: %clang_cc1 -DUSE -DCK19 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK19,CK19-64,CK19-USE +// RUN: %clang_cc1 -DUSE -DCK19 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -DUSE -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK19,CK19-64,CK19-USE +// RUN: %clang_cc1 -DUSE -DCK19 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK19,CK19-32,CK19-USE +// RUN: %clang_cc1 -DUSE -DCK19 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -DUSE -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK19,CK19-32,CK19-USE + +// RUN: %clang_cc1 -DUSE -DCK19 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s +// RUN: %clang_cc1 -DUSE -DCK19 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -DUSE -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s +// RUN: %clang_cc1 -DUSE -DCK19 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s +// RUN: %clang_cc1 -DUSE -DCK19 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -DUSE -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s + +// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK19,CK19-64,CK19-NOUSE // RUN: %clang_cc1 -DCK19 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-64 -// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK19,CK19-64,CK19-NOUSE +// RUN: %clang_cc1 -DCK19 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK19,CK19-32,CK19-NOUSE // RUN: %clang_cc1 -DCK19 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK19 --check-prefix CK19-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK19,CK19-32,CK19-NOUSE // RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s // RUN: %clang_cc1 -DCK19 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s @@ -1320,6 +1334,8 @@ void implicit_maps_template_type_capture (int a){ // RUN: %clang_cc1 -DCK19 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s // RUN: %clang_cc1 -DCK19 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY18 %s + + // SIMD-ONLY18-NOT: {{__kmpc|__tgt}} #ifdef CK19 @@ -1388,29 +1404,40 @@ void implicit_maps_template_type_capture (int a){ // CK19: [[MTYPE15:@.+]] = private {{.*}}constant [1 x i64] [i64 34] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[MTYPE16:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 33] +// CK19-USE: [[MTYPE16:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 33] +// CK19-NOUSE: [[MTYPE16:@.+]] = private {{.*}}constant [1 x i64] [i64 33] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[SIZE17:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 240] -// CK19: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 34] +// CK19-USE: [[SIZE17:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 240] +// CK19-USE: [[MTYPE17:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 34] +// CK19-NOUSE: [[SIZE17:@.+]] = private {{.*}}constant [1 x i64] [i64 240] +// CK19-NOUSE: [[MTYPE17:@.+]] = private {{.*}}constant [1 x i64] [i64 34] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[SIZE18:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 240] -// CK19: [[MTYPE18:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 35] +// CK19-USE: [[SIZE18:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 240] +// CK19-USE: [[MTYPE18:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 35] +// CK19-NOUSE: [[SIZE18:@.+]] = private {{.*}}constant [1 x i64] [i64 240] +// CK19-NOUSE: [[MTYPE18:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[MTYPE19:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 32] +// CK19-USE: [[MTYPE19:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 32] +// CK19-NOUSE: [[MTYPE19:@.+]] = private {{.*}}constant [1 x i64] [i64 32] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[SIZE20:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 4] -// CK19: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 33] +// CK19-USE: [[SIZE20:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 4] +// CK19-USE: [[MTYPE20:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 33] +// CK19-NOUSE: [[SIZE20:@.+]] = private {{.*}}constant [1 x i64] [i64 4] +// CK19-NOUSE: [[MTYPE20:@.+]] = private {{.*}}constant [1 x i64] [i64 33] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[MTYPE21:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 35] +// CK19-USE: [[MTYPE21:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 35] +// CK19-NOUSE: [[MTYPE21:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[SIZE22:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 4] -// CK19: [[MTYPE22:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 35] +// CK19-USE: [[SIZE22:@.+]] = private {{.*}}constant [2 x i64] [i64 {{8|4}}, i64 4] +// CK19-USE: [[MTYPE22:@.+]] = private {{.*}}constant [2 x i64] [i64 800, i64 35] +// CK19-NOUSE: [[SIZE22:@.+]] = private {{.*}}constant [1 x i64] [i64 4] +// CK19-NOUSE: [[MTYPE22:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK19: [[SIZE23:@.+]] = private {{.*}}constant [1 x i64] [i64 4] @@ -1441,11 +1468,14 @@ void implicit_maps_template_type_capture (int a){ // CK19: [[MTYPE29:@.+]] = private {{.*}}constant [3 x i64] [i64 35, i64 16, i64 19] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[MTYPE30:@.+]] = private {{.*}}constant [4 x i64] [i64 800, i64 800, i64 800, i64 35] +// CK19-USE: [[MTYPE30:@.+]] = private {{.*}}constant [4 x i64] [i64 800, i64 800, i64 800, i64 35] +// CK19-NOUSE: [[MTYPE30:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[SIZE31:@.+]] = private {{.*}}constant [4 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 {{8|4}}, i64 40] -// CK19: [[MTYPE31:@.+]] = private {{.*}}constant [4 x i64] [i64 800, i64 800, i64 800, i64 35] +// CK19-USE: [[SIZE31:@.+]] = private {{.*}}constant [4 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 {{8|4}}, i64 40] +// CK19-USE: [[MTYPE31:@.+]] = private {{.*}}constant [4 x i64] [i64 800, i64 800, i64 800, i64 35] +// CK19-NOUSE: [[SIZE31:@.+]] = private {{.*}}constant [1 x i64] [i64 40] +// CK19-NOUSE: [[MTYPE31:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK19: [[SIZE32:@.+]] = private {{.*}}constant [1 x i64] [i64 13728] @@ -1467,20 +1497,26 @@ void implicit_maps_template_type_capture (int a){ // CK19: [[MTYPE36:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[MTYPE37:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-USE: [[MTYPE37:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-NOUSE: [[MTYPE37:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[MTYPE38:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-USE: [[MTYPE38:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-NOUSE: [[MTYPE38:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[MTYPE39:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-USE: [[MTYPE39:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-NOUSE: [[MTYPE39:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[MTYPE40:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-USE: [[MTYPE40:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-NOUSE: [[MTYPE40:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 -// CK19: [[SIZE41:@.+]] = private {{.*}}constant [3 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 208] -// CK19: [[MTYPE41:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-USE: [[SIZE41:@.+]] = private {{.*}}constant [3 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 208] +// CK19-USE: [[MTYPE41:@.+]] = private {{.*}}constant [3 x i64] [i64 800, i64 800, i64 35] +// CK19-NOUSE: [[SIZE41:@.+]] = private {{.*}}constant [1 x i64] [i64 208] +// CK19-NOUSE: [[MTYPE41:@.+]] = private {{.*}}constant [1 x i64] [i64 35] // CK19-LABEL: @.__omp_offloading_{{.*}}explicit_maps_single{{.*}}_l{{[0-9]+}}.region_id = weak constant i8 0 // CK19: [[SIZE42:@.+]] = private {{.*}}constant [3 x i64] [i64 {{8|4}}, i64 {{8|4}}, i64 104] @@ -1510,10 +1546,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] // CK19-DAG: store i32* [[VAR0]], i32** [[CP0]] - // CK19: call void [[CALL00:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL00:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL00:@.+]]() #pragma omp target map(alloc:a) { +#ifdef USE ++a; +#endif } // Map of a scalar in nested region. @@ -1531,11 +1570,14 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] // CK19-DAG: store i32* [[VAR0]], i32** [[CP0]] - // CK19: call void [[CALL00n:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL00n:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL00n:@.+]]() #pragma omp target map(alloc:b) #pragma omp parallel { +#ifdef USE ++b; +#endif } // Map of an array. @@ -1553,10 +1595,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store [100 x i32]* [[VAR0:%.+]], [100 x i32]** [[CBP0]] // CK19-DAG: store [100 x i32]* [[VAR0]], [100 x i32]** [[CP0]] - // CK19: call void [[CALL01:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL01:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL01:@.+]]() #pragma omp target map(to:arra) { +#ifdef USE arra[50]++; +#endif } // Region 02 @@ -1572,10 +1617,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 20 - // CK19: call void [[CALL02:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL02:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL02:@.+]]() #pragma omp target map(from:arra[20:60]) { +#ifdef USE arra[50]++; +#endif } // Region 03 @@ -1591,10 +1639,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 - // CK19: call void [[CALL03:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL03:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL03:@.+]]() #pragma omp target map(tofrom:arra[:60]) { +#ifdef USE arra[50]++; +#endif } // Region 04 @@ -1610,10 +1661,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 - // CK19: call void [[CALL04:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL04:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL04:@.+]]() #pragma omp target map(alloc:arra[:]) { +#ifdef USE arra[50]++; +#endif } // Region 05 @@ -1629,10 +1683,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 15 - // CK19: call void [[CALL05:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL05:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL05:@.+]]() #pragma omp target map(to:arra[15]) { +#ifdef USE arra[15]++; +#endif } // Region 06 @@ -1652,10 +1709,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[CSVAL0]] = {{mul nuw i.+ %.*, 4|sext i32 .+ to i64}} // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} %{{.*}} - // CK19: call void [[CALL06:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL06:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL06:@.+]]() #pragma omp target map(tofrom:arra[ii:ii+23]) { +#ifdef USE arra[50]++; +#endif } // Region 07 @@ -1675,10 +1735,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[CSVAL0]] = {{mul nuw i.+ %.*, 4|sext i32 .+ to i64}} // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 - // CK19: call void [[CALL07:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL07:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL07:@.+]]() #pragma omp target map(alloc:arra[:ii]) { +#ifdef USE arra[50]++; +#endif } // Region 08 @@ -1694,10 +1757,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} %{{.*}} - // CK19: call void [[CALL08:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL08:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL08:@.+]]() #pragma omp target map(tofrom:arra[ii]) { +#ifdef USE arra[15]++; +#endif } // Map of a pointer. @@ -1715,10 +1781,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32** [[VAR0:%.+]], i32*** [[CBP0]] // CK19-DAG: store i32** [[VAR0]], i32*** [[CP0]] - // CK19: call void [[CALL09:@.+]](i32** {{[^,]+}}) + // CK19-USE: call void [[CALL09:@.+]](i32** {{[^,]+}}) + // CK19-NOUSE: call void [[CALL09:@.+]]() #pragma omp target map(from:pa) { +#ifdef USE pa[50]++; +#endif } // Region 10 @@ -1736,10 +1805,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 20 // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] - // CK19: call void [[CALL10:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL10:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL10:@.+]]() #pragma omp target map(tofrom:pa[20:60]) { +#ifdef USE pa[50]++; +#endif } // Region 11 @@ -1757,10 +1829,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 0 // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] - // CK19: call void [[CALL11:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL11:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL11:@.+]]() #pragma omp target map(alloc:pa[:60]) { +#ifdef USE pa[50]++; +#endif } // Region 12 @@ -1778,10 +1853,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 15 // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] - // CK19: call void [[CALL12:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL12:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL12:@.+]]() #pragma omp target map(to:pa[15]) { +#ifdef USE pa[15]++; +#endif } // Region 13 @@ -1803,10 +1881,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} %{{.*}} // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] - // CK19: call void [[CALL13:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL13:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL13:@.+]]() #pragma omp target map(alloc:pa[ii-23:ii]) { +#ifdef USE pa[50]++; +#endif } // Region 14 @@ -1828,10 +1909,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 0 // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] - // CK19: call void [[CALL14:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL14:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL14:@.+]]() #pragma omp target map(to:pa[:ii]) { +#ifdef USE pa[50]++; +#endif } // Region 15 @@ -1849,212 +1933,300 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} %{{.*}} // CK19-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] - // CK19: call void [[CALL15:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL15:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL15:@.+]]() #pragma omp target map(from:pa[ii+12]) { +#ifdef USE pa[15]++; +#endif } // Map of a variable-size array. int va[ii]; // Region 16 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE16]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|2}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[MTYPE16]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK19-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z:64|32]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] - // CK19-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] - - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** - // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] - // CK19-DAG: store i32* [[VAR1]], i32** [[CP1]] - // CK19-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] - // CK19-DAG: [[CSVAL1]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} - - // CK19: call void [[CALL16:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z:64|32]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] + // CK19-USE-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] + + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-USE-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-USE-DAG: store i32* [[VAR1]], i32** [[CP1]] + // CK19-USE-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] + // CK19-USE-DAG: [[CSVAL1]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-NOUSE-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-NOUSE-DAG: store i32* [[VAR0]], i32** [[CP0]] + // CK19-NOUSE-DAG: store i{{.+}} [[CSVAL0:%[^,]+]], i{{.+}}* [[S0]] + // CK19-NOUSE-DAG: [[CSVAL0]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} + + // CK19-USE: call void [[CALL16:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL16:@.+]]() #pragma omp target map(to:va) { +#ifdef USE va[50]++; +#endif } // Region 17 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE17]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE17]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|2}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[SIZE17]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[MTYPE17]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] - - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** - // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] - // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] - // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 20 - - // CK19: call void [[CALL17:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] + + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-USE-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-USE-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] + // CK19-USE-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 20 + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-NOUSE-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-NOUSE-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[VAR0]], i{{.+}} 20 + + // CK19-USE: call void [[CALL17:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL17:@.+]]() #pragma omp target map(from:va[20:60]) { +#ifdef USE va[50]++; +#endif } // Region 18 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE18]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE18]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|2}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[SIZE18]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[MTYPE18]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] - - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** - // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] - // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] - // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 0 - - // CK19: call void [[CALL18:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] + + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-USE-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-USE-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] + // CK19-USE-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 0 + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-NOUSE-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-NOUSE-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[VAR0]], i{{.+}} 0 + + // CK19-USE: call void [[CALL18:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL18:@.+]]() #pragma omp target map(tofrom:va[:60]) { +#ifdef USE va[50]++; +#endif } // Region 19 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE19]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|2}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[MTYPE19]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK19-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] - // CK19-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] - - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** - // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] - // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] - // CK19-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] - // CK19-DAG: [[CSVAL1]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} - // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 0 - - // CK19: call void [[CALL19:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] + // CK19-USE-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] + + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-USE-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-USE-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] + // CK19-USE-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] + // CK19-USE-DAG: [[CSVAL1]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} + // CK19-USE-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 0 + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-NOUSE-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-NOUSE-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK19-NOUSE-DAG: store i{{.+}} [[CSVAL0:%[^,]+]], i{{.+}}* [[S0]] + // CK19-NOUSE-DAG: [[CSVAL0]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[VAR0]], i{{.+}} 0 + + // CK19-USE: call void [[CALL19:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL19:@.+]]() #pragma omp target map(alloc:va[:]) { +#ifdef USE va[50]++; +#endif } // Region 20 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE20]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE20]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|2}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[SIZE20]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[MTYPE20]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] - - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** - // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] - // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] - // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 15 - - // CK19: call void [[CALL20:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] + + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-USE-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-USE-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] + // CK19-USE-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} 15 + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-NOUSE-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-NOUSE-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[VAR0]], i{{.+}} 15 + + // CK19-USE: call void [[CALL20:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL20:@.+]]() #pragma omp target map(to:va[15]) { +#ifdef USE va[15]++; +#endif } // Region 21 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE21]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|2}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[MTYPE21]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK19-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] - // CK19-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] - - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** - // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] - // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] - // CK19-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] - // CK19-DAG: [[CSVAL1]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} - // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} %{{.+}} - - // CK19: call void [[CALL21:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] + // CK19-USE-DAG: store i{{.+}} {{8|4}}, i{{.+}}* [[S0]] + + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-USE-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-USE-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] + // CK19-USE-DAG: store i{{.+}} [[CSVAL1:%[^,]+]], i{{.+}}* [[S1]] + // CK19-USE-DAG: [[CSVAL1]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} + // CK19-USE-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} %{{.+}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-NOUSE-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-NOUSE-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK19-NOUSE-DAG: store i{{.+}} [[CSVAL0:%[^,]+]], i{{.+}}* [[S0]] + // CK19-NOUSE-DAG: [[CSVAL0]] = {{mul nuw i64 %.*, 4|sext i32 .+ to i64}} + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[VAR0]], i{{.+}} %{{.+}} + + // CK19-USE: call void [[CALL21:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL21:@.+]]() #pragma omp target map(tofrom:va[ii:ii+23]) { +#ifdef USE va[50]++; +#endif } // Region 22 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 2, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[SIZE22]], {{.+}}getelementptr {{.+}}[2 x i{{.+}}]* [[MTYPE22]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|2}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[SIZE22]], {{.+}}getelementptr {{.+}}[{{1|2}} x i{{.+}}]* [[MTYPE22]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] - - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** - // CK19-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] - // CK19-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] - // CK19-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} %{{.+}} - - // CK19: call void [[CALL22:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] {{%.+}}, i[[Z]]* [[CP0]] + + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i32** + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i32** + // CK19-USE-DAG: store i32* [[VAR1:%.+]], i32** [[CBP1]] + // CK19-USE-DAG: store i32* [[SEC1:%.+]], i32** [[CP1]] + // CK19-USE-DAG: [[SEC1]] = getelementptr {{.*}}i32* [[VAR1]], i{{.+}} %{{.+}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i32** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i32** + // CK19-NOUSE-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] + // CK19-NOUSE-DAG: store i32* [[SEC0:%.+]], i32** [[CP0]] + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[VAR0]], i{{.+}} %{{.+}} + + // CK19-USE: call void [[CALL22:@.+]](i{{.+}} {{[^,]+}}, i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL22:@.+]]() #pragma omp target map(tofrom:va[ii]) { +#ifdef USE va[15]++; +#endif } // Always. @@ -2070,10 +2242,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] // CK19-DAG: store i32* [[VAR0]], i32** [[CP0]] - // CK19: call void [[CALL23:@.+]](i32* {{[^,]+}}) + // CK19-USE: call void [[CALL23:@.+]](i32* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL23:@.+]]() #pragma omp target map(always, tofrom: a) { +#ifdef USE a++; +#endif } // Multidimensional arrays. @@ -2092,10 +2267,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store [4 x [5 x [6 x i32]]]* [[VAR0:%.+]], [4 x [5 x [6 x i32]]]** [[CBP0]] // CK19-DAG: store [4 x [5 x [6 x i32]]]* [[VAR0]], [4 x [5 x [6 x i32]]]** [[CP0]] - // CK19: call void [[CALL24:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL24:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL24:@.+]]() #pragma omp target map(tofrom: marr) { +#ifdef USE marr[1][2][3]++; +#endif } // Region 25 @@ -2113,10 +2291,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC00]] = getelementptr {{.*}}[5 x [6 x i32]]* [[SEC000:[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[SEC000]] = getelementptr {{.*}}[4 x [5 x [6 x i32]]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 - // CK19: call void [[CALL25:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL25:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL25:@.+]]() #pragma omp target map(tofrom: marr[1][2][2:4]) { +#ifdef USE marr[1][2][3]++; +#endif } // Region 26 @@ -2134,10 +2315,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC00]] = getelementptr {{.*}}[5 x [6 x i32]]* [[SEC000:[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[SEC000]] = getelementptr {{.*}}[4 x [5 x [6 x i32]]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 - // CK19: call void [[CALL26:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL26:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL26:@.+]]() #pragma omp target map(tofrom: marr[1][2][:]) { +#ifdef USE marr[1][2][3]++; +#endif } // Region 27 @@ -2155,10 +2339,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC00]] = getelementptr {{.*}}[5 x [6 x i32]]* [[SEC000:[^,]+]], i{{.+}} 0, i{{.+}} 2 // CK19-DAG: [[SEC000]] = getelementptr {{.*}}[4 x [5 x [6 x i32]]]* [[VAR0]], i{{.+}} 0, i{{.+}} 1 - // CK19: call void [[CALL27:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL27:@.+]]([4 x [5 x [6 x i32]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL27:@.+]]() #pragma omp target map(tofrom: marr[1][2][3]) { +#ifdef USE marr[1][2][3]++; +#endif } // Region 28 @@ -2200,10 +2387,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC22222]] = getelementptr {{.*}}i32*** [[SEC222222:[^,]+]], i{{.+}} 1 // CK19-DAG: [[SEC222222]] = load i32***, i32**** [[PTR]], - // CK19: call void [[CALL28:@.+]](i32*** {{[^,]+}}) + // CK19-USE: call void [[CALL28:@.+]](i32*** {{[^,]+}}) + // CK19-NOUSE: call void [[CALL28:@.+]]() #pragma omp target map(tofrom: mptr[1][2][2:4]) { +#ifdef USE mptr[1][2][3]++; +#endif } // Region 29 @@ -2245,110 +2435,141 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC22222]] = getelementptr {{.*}}i32*** [[SEC222222:[^,]+]], i{{.+}} 1 // CK19-DAG: [[SEC222222]] = load i32***, i32**** [[PTR]], - // CK19: call void [[CALL29:@.+]](i32*** {{[^,]+}}) + // CK19-USE: call void [[CALL29:@.+]](i32*** {{[^,]+}}) + // CK19-NOUSE: call void [[CALL29:@.+]]() #pragma omp target map(tofrom: mptr[1][2][3]) { +#ifdef USE mptr[1][2][3]++; +#endif } // Multidimensional VLA. double mva[23][ii][ii+5]; // Region 30 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE30]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|4}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[{{1|4}} x i{{.+}}]* [[MTYPE30]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK19-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] 23, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] 23, i[[Z]]* [[CP0]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S0]] + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] 23, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] 23, i[[Z]]* [[CP0]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S0]] // - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] - // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S1]] - // CK19-64-DAG: [[VAR1]] = zext i32 %{{[^,]+}} to i64 - // CK19-64-DAG: [[VAR11]] = zext i32 %{{[^,]+}} to i64 + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-USE-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S1]] + // CK19-64-USE-DAG: [[VAR1]] = zext i32 %{{[^,]+}} to i64 + // CK19-64-USE-DAG: [[VAR11]] = zext i32 %{{[^,]+}} to i64 // - // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to i[[Z]]* - // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR2:%.+]], i[[Z]]* [[CBP2]] - // CK19-DAG: store i[[Z]] [[VAR22:%.+]], i[[Z]]* [[CP2]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S2]] - // CK19-64-DAG: [[VAR2]] = zext i32 %{{[^,]+}} to i64 - // CK19-64-DAG: [[VAR22]] = zext i32 %{{[^,]+}} to i64 + // CK19-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to i[[Z]]* + // CK19-USE-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR2:%.+]], i[[Z]]* [[CBP2]] + // CK19-USE-DAG: store i[[Z]] [[VAR22:%.+]], i[[Z]]* [[CP2]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S2]] + // CK19-64-USE-DAG: [[VAR2]] = zext i32 %{{[^,]+}} to i64 + // CK19-64-USE-DAG: [[VAR22]] = zext i32 %{{[^,]+}} to i64 // - // CK19-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 - // CK19-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK19-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 3 - // CK19-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double** - // CK19-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** - // CK19-DAG: store double* [[VAR3:%.+]], double** [[CBP3]] - // CK19-DAG: store double* [[VAR3]], double** [[CP3]] - // CK19-DAG: store i64 [[CSVAL3:%[^,]+]], i64* [[S3]] - // CK19-DAG: [[CSVAL3]] = {{mul nuw i64 %[^,]+, 8|sext i32 .+ to i64}} - - // CK19: call void [[CALL30:@.+]](i[[Z]] 23, i[[Z]] %{{[^,]+}}, i[[Z]] %{{[^,]+}}, double* %{{[^,]+}}) + // CK19-USE-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 + // CK19-USE-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 + // CK19-USE-DAG: [[S3:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 3 + // CK19-USE-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double** + // CK19-USE-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** + // CK19-USE-DAG: store double* [[VAR3:%.+]], double** [[CBP3]] + // CK19-USE-DAG: store double* [[VAR3]], double** [[CP3]] + // CK19-USE-DAG: store i64 [[CSVAL3:%[^,]+]], i64* [[S3]] + // CK19-USE-DAG: [[CSVAL3]] = {{mul nuw i64 %[^,]+, 8|sext i32 .+ to i64}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to double** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double** + // CK19-NOUSE-DAG: store double* [[VAR0:%.+]], double** [[CBP0]] + // CK19-NOUSE-DAG: store double* [[VAR0]], double** [[CP0]] + // CK19-NOUSE-DAG: store i64 [[CSVAL0:%[^,]+]], i64* [[S0]] + // CK19-NOUSE-DAG: [[CSVAL0]] = {{mul nuw i64 %[^,]+, 8|sext i32 .+ to i64}} + + // CK19-USE: call void [[CALL30:@.+]](i[[Z]] 23, i[[Z]] %{{[^,]+}}, i[[Z]] %{{[^,]+}}, double* %{{[^,]+}}) + // CK19-NOUSE: call void [[CALL30:@.+]]() #pragma omp target map(tofrom: mva) { +#ifdef USE mva[1][2][3]++; +#endif } // Region 31 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 4, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[SIZE31]], {{.+}}getelementptr {{.+}}[4 x i{{.+}}]* [[MTYPE31]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|4}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[{{1|4}} x i{{.+}}]* [[SIZE31]], {{.+}}getelementptr {{.+}}[{{1|4}} x i{{.+}}]* [[MTYPE31]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] 23, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] 23, i[[Z]]* [[CP0]] + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] 23, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] 23, i[[Z]]* [[CP0]] // - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] - // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-USE-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // - // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to i[[Z]]* - // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR2:%.+]], i[[Z]]* [[CBP2]] - // CK19-DAG: store i[[Z]] [[VAR22:%.+]], i[[Z]]* [[CP2]] + // CK19-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to i[[Z]]* + // CK19-USE-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR2:%.+]], i[[Z]]* [[CBP2]] + // CK19-USE-DAG: store i[[Z]] [[VAR22:%.+]], i[[Z]]* [[CP2]] // - // CK19-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 - // CK19-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 - // CK19-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double** - // CK19-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** - // CK19-DAG: store double* [[VAR3:%.+]], double** [[CBP3]] - // CK19-DAG: store double* [[SEC3:%.+]], double** [[CP3]] - // CK19-DAG: [[SEC3]] = getelementptr {{.*}}double* [[SEC33:%.+]], i[[Z]] 0 - // CK19-DAG: [[SEC33]] = getelementptr {{.*}}double* [[SEC333:%.+]], i[[Z]] [[IDX3:%.+]] - // CK19-DAG: [[IDX3]] = mul nsw i[[Z]] %{{[^,]+}}, %{{[^,]+}} - // CK19-DAG: [[SEC333]] = getelementptr {{.*}}double* [[VAR3]], i[[Z]] [[IDX33:%.+]] - // CK19-DAG: [[IDX33]] = mul nsw i[[Z]] 1, %{{[^,]+}} - - // CK19: call void [[CALL31:@.+]](i[[Z]] 23, i[[Z]] %{{[^,]+}}, i[[Z]] %{{[^,]+}}, double* %{{[^,]+}}) + // CK19-USE-DAG: [[BP3:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 3 + // CK19-USE-DAG: [[P3:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 3 + // CK19-USE-DAG: [[CBP3:%.+]] = bitcast i8** [[BP3]] to double** + // CK19-USE-DAG: [[CP3:%.+]] = bitcast i8** [[P3]] to double** + // CK19-USE-DAG: store double* [[VAR3:%.+]], double** [[CBP3]] + // CK19-USE-DAG: store double* [[SEC3:%.+]], double** [[CP3]] + // CK19-USE-DAG: [[SEC3]] = getelementptr {{.*}}double* [[SEC33:%.+]], i[[Z]] 0 + // CK19-USE-DAG: [[SEC33]] = getelementptr {{.*}}double* [[SEC333:%.+]], i[[Z]] [[IDX3:%.+]] + // CK19-USE-DAG: [[IDX3]] = mul nsw i[[Z]] %{{[^,]+}}, %{{[^,]+}} + // CK19-USE-DAG: [[SEC333]] = getelementptr {{.*}}double* [[VAR3]], i[[Z]] [[IDX33:%.+]] + // CK19-USE-DAG: [[IDX33]] = mul nsw i[[Z]] 1, %{{[^,]+}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to double** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double** + // CK19-NOUSE-DAG: store double* [[VAR0:%.+]], double** [[CBP0]] + // CK19-NOUSE-DAG: store double* [[SEC0:%.+]], double** [[CP0]] + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.*}}double* [[SEC00:%.+]], i[[Z:64|32]] 0 + // CK19-NOUSE-DAG: [[SEC00]] = getelementptr {{.*}}double* [[SEC000:%.+]], i[[Z]] [[IDX0:%.+]] + // CK19-NOUSE-DAG: [[IDX0]] = mul nsw i[[Z]] %{{[^,]+}}, %{{[^,]+}} + // CK19-NOUSE-DAG: [[SEC000]] = getelementptr {{.*}}double* [[VAR0]], i[[Z]] [[IDX00:%.+]] + // CK19-NOUSE-DAG: [[IDX00]] = mul nsw i[[Z]] 1, %{{[^,]+}} + + // CK19-USE: call void [[CALL31:@.+]](i[[Z]] 23, i[[Z]] %{{[^,]+}}, i[[Z]] %{{[^,]+}}, double* %{{[^,]+}}) + // CK19-NOUSE: call void [[CALL31:@.+]]() #pragma omp target map(tofrom: mva[1][ii-2][:5]) { +#ifdef USE mva[1][2][3]++; +#endif } // Multidimensional array sections. @@ -2368,10 +2589,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0:%.+]], [11 x [12 x [13 x double]]]** [[CBP0]] // CK19-DAG: store [11 x [12 x [13 x double]]]* [[VAR0]], [11 x [12 x [13 x double]]]** [[CP0]] - // CK19: call void [[CALL32:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL32:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL32:@.+]]() #pragma omp target map(marras) { +#ifdef USE marras[1][2][3]++; +#endif } // Region 33 @@ -2387,10 +2611,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store [12 x [13 x double]]* [[SEC0:%.+]], [12 x [13 x double]]** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i[[Z]] 0, i[[Z]] 0 - // CK19: call void [[CALL33:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL33:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL33:@.+]]() #pragma omp target map(marras[:]) { +#ifdef USE marras[1][2][3]++; +#endif } // Region 34 @@ -2406,10 +2633,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store [12 x [13 x double]]* [[SEC0:%.+]], [12 x [13 x double]]** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i[[Z]] 0, i[[Z]] 0 - // CK19: call void [[CALL34:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL34:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL34:@.+]]() #pragma omp target map(marras[:][:][:]) { +#ifdef USE marras[1][2][3]++; +#endif } // Region 35 @@ -2431,10 +2661,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC00]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i[[Z]] 0, i[[Z]] 1 // CK19-DAG: [[CSVAL0]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} - // CK19: call void [[CALL35:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL35:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL35:@.+]]() #pragma omp target map(marras[1][:ii][:]) { +#ifdef USE marras[1][2][3]++; +#endif } // Region 36 @@ -2452,211 +2685,285 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC00]] = getelementptr {{.+}}[12 x [13 x double]]* [[SEC000:%[^,]+]], i{{.+}} 0, i{{.+}} 0 // CK19-DAG: [[SEC000]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i{{.+}} 0, i{{.+}} 0 - // CK19: call void [[CALL36:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL36:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL36:@.+]]() #pragma omp target map(marras[:1][:2][:13]) { +#ifdef USE marras[1][2][3]++; +#endif } // Region 37 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE37]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|3}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[{{1|3}} x i{{.+}}]* [[MTYPE37]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK19-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S0]] + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S0]] // - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] - // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S1]] + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-USE-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S1]] // - // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** - // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** - // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] - // CK19-DAG: store [13 x double]* [[VAR2]], [13 x double]** [[CP2]] - // CK19-DAG: store i64 [[CSVAL2:%[^,]+]], i64* [[S2]] - // CK19-DAG: [[CSVAL2]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} - - // CK19: call void [[CALL37:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-USE-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-USE-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-USE-DAG: store [13 x double]* [[VAR2]], [13 x double]** [[CP2]] + // CK19-USE-DAG: store i64 [[CSVAL2:%[^,]+]], i64* [[S2]] + // CK19-USE-DAG: [[CSVAL2]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [13 x double]** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [13 x double]** + // CK19-NOUSE-DAG: store [13 x double]* [[VAR0:%.+]], [13 x double]** [[CBP0]] + // CK19-NOUSE-DAG: store [13 x double]* [[VAR0]], [13 x double]** [[CP0]] + // CK19-NOUSE-DAG: store i64 [[CSVAL0:%[^,]+]], i64* [[S0]] + // CK19-NOUSE-DAG: [[CSVAL0]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} + + // CK19-USE: call void [[CALL37:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-NOUSE: call void [[CALL37:@.+]]() #pragma omp target map(mvlaas) { +#ifdef USE mvlaas[1][2][3]++; +#endif } // Region 38 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE38]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|3}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[{{1|3}} x i{{.+}}]* [[MTYPE38]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK19-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S0]] + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S0]] // - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] - // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S1]] + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-USE-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S1]] // - // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** - // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** - // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] - // CK19-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] - // CK19-DAG: store i64 [[CSVAL2:%[^,]+]], i64* [[S2]] - // CK19-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC22:%[^,]+]] - // CK19-DAG: [[SEC22]] = mul nsw i[[Z]] 0, %{{[^,]+}} - // CK19-DAG: [[CSVAL2]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} - - // CK19: call void [[CALL38:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-USE-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-USE-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-USE-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] + // CK19-USE-DAG: store i64 [[CSVAL2:%[^,]+]], i64* [[S2]] + // CK19-USE-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC22:%[^,]+]] + // CK19-USE-DAG: [[SEC22]] = mul nsw i[[Z]] 0, %{{[^,]+}} + // CK19-USE-DAG: [[CSVAL2]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [13 x double]** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [13 x double]** + // CK19-NOUSE-DAG: store [13 x double]* [[VAR0:%.+]], [13 x double]** [[CBP0]] + // CK19-NOUSE-DAG: store [13 x double]* [[SEC0:%.+]], [13 x double]** [[CP0]] + // CK19-NOUSE-DAG: store i64 [[CSVAL0:%[^,]+]], i64* [[S0]] + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.+}}[13 x double]* [[VAR0]], i[[Z]] [[SEC00:%[^,]+]] + // CK19-NOUSE-DAG: [[SEC00]] = mul nsw i[[Z]] 0, %{{[^,]+}} + // CK19-NOUSE-DAG: [[CSVAL0]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} + + // CK19-USE: call void [[CALL38:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-NOUSE: call void [[CALL38:@.+]]() #pragma omp target map(mvlaas[:]) { +#ifdef USE mvlaas[1][2][3]++; +#endif } // Region 39 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE39]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|3}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[{{1|3}} x i{{.+}}]* [[MTYPE39]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK19-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S0]] + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S0]] // - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] - // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S1]] + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-USE-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S1]] // - // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** - // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** - // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] - // CK19-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] - // CK19-DAG: store i64 [[CSVAL2:%[^,]+]], i64* [[S2]] - // CK19-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC22:%[^,]+]] - // CK19-DAG: [[SEC22]] = mul nsw i[[Z]] 0, %{{[^,]+}} - // CK19-DAG: [[CSVAL2]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} - - // CK19: call void [[CALL39:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-USE-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-USE-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-USE-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] + // CK19-USE-DAG: store i64 [[CSVAL2:%[^,]+]], i64* [[S2]] + // CK19-USE-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC22:%[^,]+]] + // CK19-USE-DAG: [[SEC22]] = mul nsw i[[Z]] 0, %{{[^,]+}} + // CK19-USE-DAG: [[CSVAL2]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [13 x double]** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [13 x double]** + // CK19-NOUSE-DAG: store [13 x double]* [[VAR0:%.+]], [13 x double]** [[CBP0]] + // CK19-NOUSE-DAG: store [13 x double]* [[SEC0:%.+]], [13 x double]** [[CP0]] + // CK19-NOUSE-DAG: store i64 [[CSVAL0:%[^,]+]], i64* [[S0]] + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.+}}[13 x double]* [[VAR0]], i[[Z]] [[SEC00:%[^,]+]] + // CK19-NOUSE-DAG: [[SEC00]] = mul nsw i[[Z]] 0, %{{[^,]+}} + // CK19-NOUSE-DAG: [[CSVAL0]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} + + // CK19-USE: call void [[CALL39:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-NOUSE: call void [[CALL39:@.+]]() #pragma omp target map(mvlaas[:][:][:]) { +#ifdef USE mvlaas[1][2][3]++; +#endif } // Region 40 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE40]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|3}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], i64* [[GEPS:%.+]], {{.+}}getelementptr {{.+}}[{{1|3}} x i{{.+}}]* [[MTYPE40]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // CK19-DAG: [[GEPS]] = getelementptr inbounds {{.+}}[[S:%[^,]+]] // - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S0]] + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S0]] // - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] - // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] - // CK19-DAG: store i64 {{8|4}}, i64* [[S1]] + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[S1:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-USE-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] + // CK19-USE-DAG: store i64 {{8|4}}, i64* [[S1]] // - // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** - // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** - // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] - // CK19-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] - // CK19-DAG: store i64 [[CSVAL2:%[^,]+]], i64* [[S2]] - // CK19-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[SEC22:%[^,]+]], i[[Z]] 0 - // CK19-DAG: [[SEC22]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC222:%[^,]+]] - // CK19-DAG: [[SEC222]] = mul nsw i[[Z]] 1, %{{[^,]+}} - - // CK19: call void [[CALL40:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[S2:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-USE-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-USE-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-USE-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] + // CK19-USE-DAG: store i64 [[CSVAL2:%[^,]+]], i64* [[S2]] + // CK19-USE-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[SEC22:%[^,]+]], i[[Z]] 0 + // CK19-USE-DAG: [[SEC22]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC222:%[^,]+]] + // CK19-USE-DAG: [[SEC222]] = mul nsw i[[Z]] 1, %{{[^,]+}} + + // CK19-NOUSE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[S0:%.+]] = getelementptr inbounds {{.+}}[[S]], i{{.+}} 0, i{{.+}} 0 + // CK19-NOUSE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [13 x double]** + // CK19-NOUSE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [13 x double]** + // CK19-NOUSE-DAG: store [13 x double]* [[VAR0:%.+]], [13 x double]** [[CBP0]] + // CK19-NOUSE-DAG: store [13 x double]* [[SEC0:%.+]], [13 x double]** [[CP0]] + // CK19-NOUSE-DAG: store i64 [[CSVAL0:%[^,]+]], i64* [[S0]] + // CK19-NOUSE-DAG: [[SEC0]] = getelementptr {{.+}}[13 x double]* [[SEC00:%[^,]+]], i[[Z]] 0 + // CK19-NOUSE-DAG: [[SEC00]] = getelementptr {{.+}}[13 x double]* [[VAR0]], i[[Z]] [[SEC000:%[^,]+]] + // CK19-NOUSE-DAG: [[SEC000]] = mul nsw i[[Z]] 1, %{{[^,]+}} + + // CK19-USE: call void [[CALL40:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-NOUSE: call void [[CALL40:@.+]]() #pragma omp target map(mvlaas[1][:ii][:]) { +#ifdef USE mvlaas[1][2][3]++; +#endif } // Region 41 - // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 3, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[SIZE41]], {{.+}}getelementptr {{.+}}[3 x i{{.+}}]* [[MTYPE41]]{{.+}}, i8** null) + // CK19-DAG: call i32 @__tgt_target_mapper(i64 {{[^,]+}}, i8* {{[^,]+}}, i32 {{1|3}}, i8** [[GEPBP:%.+]], i8** [[GEPP:%.+]], {{.+}}getelementptr {{.+}}[{{1|3}} x i{{.+}}]* [[SIZE41]], {{.+}}getelementptr {{.+}}[{{1|3}} x i{{.+}}]* [[MTYPE41]]{{.+}}, i8** null) // CK19-DAG: [[GEPBP]] = getelementptr inbounds {{.+}}[[BP:%[^,]+]] // CK19-DAG: [[GEPP]] = getelementptr inbounds {{.+}}[[P:%[^,]+]] // - // CK19-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 - // CK19-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* - // CK19-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] - // CK19-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] + // CK19-USE-DAG: [[BP0:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to i[[Z]]* + // CK19-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CBP0]] + // CK19-USE-DAG: store i[[Z]] 11, i[[Z]]* [[CP0]] // - // CK19-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 - // CK19-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* - // CK19-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* - // CK19-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] - // CK19-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] + // CK19-USE-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1 + // CK19-USE-DAG: [[CBP1:%.+]] = bitcast i8** [[BP1]] to i[[Z]]* + // CK19-USE-DAG: [[CP1:%.+]] = bitcast i8** [[P1]] to i[[Z]]* + // CK19-USE-DAG: store i[[Z]] [[VAR1:%.+]], i[[Z]]* [[CBP1]] + // CK19-USE-DAG: store i[[Z]] [[VAR11:%.+]], i[[Z]]* [[CP1]] // - // CK19-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 - // CK19-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** - // CK19-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** - // CK19-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] - // CK19-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] - // CK19-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[SEC22:%[^,]+]], i[[Z]] 0 - // CK19-DAG: [[SEC22]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC222:%[^,]+]] - // CK19-DAG: [[SEC222]] = mul nsw i[[Z]] 0, %{{[^,]+}} - - // CK19: call void [[CALL41:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[P2:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 2 + // CK19-USE-DAG: [[CBP2:%.+]] = bitcast i8** [[BP2]] to [13 x double]** + // CK19-USE-DAG: [[CP2:%.+]] = bitcast i8** [[P2]] to [13 x double]** + // CK19-USE-DAG: store [13 x double]* [[VAR2:%.+]], [13 x double]** [[CBP2]] + // CK19-USE-DAG: store [13 x double]* [[SEC2:%.+]], [13 x double]** [[CP2]] + // CK19-USE-DAG: [[SEC2]] = getelementptr {{.+}}[13 x double]* [[SEC22:%[^,]+]], i[[Z]] 0 + // CK19-USE-DAG: [[SEC22]] = getelementptr {{.+}}[13 x double]* [[VAR2]], i[[Z]] [[SEC222:%[^,]+]] + // CK19-USE-DAG: [[SEC222]] = mul nsw i[[Z]] 0, %{{[^,]+}} + // CK19-USE-DAG: [[BP2:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 2 + + // CK19-NO-USE-DAG: [[P0:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 0 + // CK19-NO-USE-DAG: [[CBP0:%.+]] = bitcast i8** [[BP0]] to [13 x double]** + // CK19-NO-USE-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to [13 x double]** + // CK19-NO-USE-DAG: store [13 x double]* [[VAR0:%.+]], [13 x double]** [[CBP0]] + // CK19-NO-USE-DAG: store [13 x double]* [[SEC0:%.+]], [13 x double]** [[CP0]] + // CK19-NO-USE-DAG: [[SEC0]] = getelementptr {{.+}}[13 x double]* [[SEC00:%[^,]+]], i[[Z]] 0 + // CK19-NO-USE-DAG: [[SEC00]] = getelementptr {{.+}}[13 x double]* [[VAR0]], i[[Z]] [[SEC000:%[^,]+]] + // CK19-NO-USE-DAG: [[SEC000]] = mul nsw i[[Z]] 0, %{{[^,]+}} + + // CK19-USE: call void [[CALL41:@.+]](i[[Z]] 11, i[[Z]] %{{[^,]+}}, [13 x double]* %{{[^,]+}}) + // CK19-NOUSE: call void [[CALL41:@.+]]() #pragma omp target map(mvlaas[:1][:2][:13]) { +#ifdef USE mvlaas[1][2][3]++; +#endif } // Region 42 @@ -2698,10 +3005,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC22222]] = getelementptr {{.*}}double*** [[SEC222222:[^,]+]], i{{.+}} 0 // CK19-DAG: [[SEC222222]] = load double***, double**** [[PTR]], - // CK19: call void [[CALL42:@.+]](double*** {{[^,]+}}) + // CK19-USE: call void [[CALL42:@.+]](double*** {{[^,]+}}) + // CK19-NOUSE: call void [[CALL42:@.+]]() #pragma omp target map(mptras[:1][2][:13]) { +#ifdef USE mptras[1][2][3]++; +#endif } // Region 43 - the memory is not contiguous for this map - will map the whole last dimension. @@ -2723,10 +3033,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: [[SEC00]] = getelementptr {{.+}}[11 x [12 x [13 x double]]]* [[VAR0]], i[[Z]] 0, i[[Z]] 1 // CK19-DAG: [[CSVAL0]] = {{mul nuw i64 %[^,]+, 104|sext i32 .+ to i64}} - // CK19: call void [[CALL43:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-USE: call void [[CALL43:@.+]]([11 x [12 x [13 x double]]]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL43:@.+]]() #pragma omp target map(marras[1][:ii][1:]) { +#ifdef USE marras[1][2][3]++; +#endif } // Region 44 @@ -2742,10 +3055,13 @@ void explicit_maps_single (int ii){ // CK19-DAG: store i32* [[SEC0:%[^,]+]], i32** [[CP0]] // CK19-DAG: [[SEC0]] = getelementptr {{.*}}[100 x i32]* [[VAR0]], i{{.+}} 0, i{{.+}} 20 - // CK19: call void [[CALL44:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-USE: call void [[CALL44:@.+]]([100 x i32]* {{[^,]+}}) + // CK19-NOUSE: call void [[CALL44:@.+]]() #pragma omp target map(from:arra[20:]) { +#ifdef USE arra[50]++; +#endif } } @@ -2926,12 +3242,26 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f #endif ///==========================================================================/// -// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-64 +// RUN: %clang_cc1 -DUSE -DCK21 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK21,CK21-64,CK21-USE +// RUN: %clang_cc1 -DUSE -DCK21 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -DUSE -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK21,CK21-64,CK21-USE +// RUN: %clang_cc1 -DUSE -DCK21 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK21,CK21-32,CK21-USE +// RUN: %clang_cc1 -DUSE -DCK21 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -DUSE -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK21,CK21-32,CK21-USE + +// RUN: %clang_cc1 -DUSE -DCK21 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s +// RUN: %clang_cc1 -DUSE -DCK21 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -DUSE -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s +// RUN: %clang_cc1 -DUSE -DCK21 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s +// RUN: %clang_cc1 -DUSE -DCK21 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s +// RUN: %clang_cc1 -DUSE -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s + +// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK21,CK21-64,CK21-NOUSE // RUN: %clang_cc1 -DCK21 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-64 -// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK21,CK21-64,CK21-NOUSE +// RUN: %clang_cc1 -DCK21 -verify -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK21,CK21-32,CK21-NOUSE // RUN: %clang_cc1 -DCK21 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s -// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefix CK21 --check-prefix CK21-32 +// RUN: %clang_cc1 -fopenmp -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap %s --check-prefixes=CK21,CK21-32,CK21-NOUSE // RUN: %clang_cc1 -DCK21 -verify -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -triple powerpc64le-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s // RUN: %clang_cc1 -DCK21 -fopenmp-simd -fopenmp-targets=powerpc64le-ibm-linux-gnu -x c++ -std=c++11 -triple powerpc64le-unknown-unknown -emit-pch -o %t %s @@ -2939,6 +3269,7 @@ void explicit_maps_references_and_function_args (int a, float b, int (&c)[10], f // RUN: %clang_cc1 -DCK21 -verify -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -emit-llvm %s -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s // RUN: %clang_cc1 -DCK21 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -std=c++11 -triple i386-unknown-unknown -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp-simd -fopenmp-targets=i386-pc-linux-gnu -x c++ -triple i386-unknown-unknown -std=c++11 -include-pch %t -verify %s -emit-llvm -o - | FileCheck -allow-deprecated-dag-overlap --check-prefix SIMD-ONLY20 %s + // SIMD-ONLY20-NOT: {{__kmpc|__tgt}} #ifdef CK21 // CK21: [[ST:%.+]] = type { i32, i32, float* } @@ -3002,10 +3333,13 @@ struct CC { // CK21-DAG: store i64 {{.+}}, i64* [[S1]] // CK21-DAG: [[SEC1]] = getelementptr {{.*}}[[ST]]* [[VAR1:%.+]], i{{.+}} 0, i{{.+}} 0 - // CK21: call void [[CALL00:@.+]]([[ST]]* {{[^,]+}}) + // CK21-USE: call void [[CALL00:@.+]]([[ST]]* {{[^,]+}}) + // CK21-NOUSE: call void [[CALL00:@.+]]() #pragma omp target map(A) { +#ifdef USE A += 1; +#endif } // Region 01 @@ -3023,10 +3357,13 @@ struct CC { // CK21-DAG: [[SEC0]] = getelementptr {{.*}}i32* [[RVAR00:%.+]], i{{.+}} 0 // CK21-DAG: [[RVAR00]] = load i32*, i32** [[VAR0]] - // CK21: call void [[CALL01:@.+]](i32* {{[^,]+}}) + // CK21-USE: call void [[CALL01:@.+]](i32* {{[^,]+}}) + // CK21-NOUSE: call void [[CALL01:@.+]]() #pragma omp target map(lb[:X]) { +#ifdef USE lb[4] += 1; +#endif } // Region 02 @@ -3057,10 +3394,13 @@ struct CC { // CK21-DAG: [[RVAR1]] = load float*, float** [[SEC1_:%[^,]+]] // CK21-DAG: [[SEC1_]] = getelementptr {{.*}}[[ST]]* [[VAR0]], i{{.+}} 0, i{{.+}} 2 - // CK21: call void [[CALL02:@.+]]([[ST]]* {{[^,]+}}) + // CK21-USE: call void [[CALL02:@.+]]([[ST]]* {{[^,]+}}) + // CK21-NOUSE: call void [[CALL02:@.+]]() #pragma omp target map(from:B[X:X+2]) { +#ifdef USE B[2] += 1.0f; +#endif } // Region 03 @@ -3075,10 +3415,13 @@ struct CC { // CK21-DAG: store [123 x float]* [[VAR0:%.+]], [123 x float]** [[CBP0]] // CK21-DAG: store [123 x float]* [[VAR0]], [123 x float]** [[CP0]] - // CK21: call void [[CALL03:@.+]]([123 x float]* {{[^,]+}}) + // CK21-USE: call void [[CALL03:@.+]]([123 x float]* {{[^,]+}}) + // CK21-NOUSE: call void [[CALL03:@.+]]() #pragma omp target map(from:la) { +#ifdef USE la[3] += 1.0f; +#endif } // Region 04 @@ -3093,10 +3436,13 @@ struct CC { // CK21-DAG: store i32* [[VAR0:%.+]], i32** [[CBP0]] // CK21-DAG: store i32* [[VAR0]], i32** [[CP0]] - // CK21: call void [[CALL04:@.+]](i32* {{[^,]+}}) + // CK21-USE: call void [[CALL04:@.+]](i32* {{[^,]+}}) + // CK21-NOUSE: call void [[CALL04:@.+]]() #pragma omp target map(from:arg) { +#ifdef USE arg +=1; +#endif } // Make sure the extra flag is passed to the second map. @@ -3135,11 +3481,14 @@ struct CC { // CK21-DAG: store i64 {{.+}}, i64* [[S2]] // CK21-DAG: [[SEC2]] = getelementptr {{.*}}[[ST]]* [[VAR2]], i{{.+}} 0, i{{.+}} 1 - // CK21: call void [[CALL05:@.+]]([[ST]]* {{[^,]+}}) + // CK21-USE: call void [[CALL05:@.+]]([[ST]]* {{[^,]+}}) + // CK21-NOUSE: call void [[CALL05:@.+]]() #pragma omp target map(A, A2) { +#ifdef USE A += 1; A2 += 1; +#endif } return A; } diff --git a/clang/test/OpenMP/target_teams_map_codegen.cpp b/clang/test/OpenMP/target_teams_map_codegen.cpp index 00d2839781075..328e45a652a91 100644 --- a/clang/test/OpenMP/target_teams_map_codegen.cpp +++ b/clang/test/OpenMP/target_teams_map_codegen.cpp @@ -20,15 +20,16 @@ #ifndef HEADER #define HEADER +// HOST: @[[MAPTYPES_PRIVATE:.offload_maptypes[0-9.]*]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] // HOST: @[[MAPTYPES_FIRSTPRIVATE:.offload_maptypes[0-9.]*]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] // HOST: @[[MAPTYPES_REDUCTION:.offload_maptypes[0-9.]*]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] // HOST: @[[MAPTYPES_FROM:.offload_maptypes[0-9.]*]] = private {{.*}}constant [1 x i64] [i64 34] // HOST: @[[MAPTYPES_TO:.offload_maptypes[0-9.]*]] = private {{.*}}constant [1 x i64] [i64 33] // HOST: @[[MAPTYPES_ALLOC:.offload_maptypes[0-9.]*]] = private {{.*}}constant [1 x i64] [i64 32] -// HOST: @[[MAPTYPES_ARRAY_R0:.offload_maptypes[0-9.]*]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] -// HOST: @[[MAPTYPES_ARRAY_R1:.offload_maptypes[0-9.]*]] = private {{.*}}constant [2 x i64] [i64 33, i64 33] -// HOST-INT128: @[[MAPTYPES_INT128_R0:.offload_maptypes[0-9.]*]] = private {{.*}}constant [2 x i64] [i64 35, i64 35] -// HOST-INT128: @[[MAPTYPES_INT128_R1:.offload_maptypes[0-9.]*]] = private {{.*}}constant [2 x i64] [i64 34, i64 34] +// HOST: @[[MAPTYPES_ARRAY_R0:.offload_maptypes[0-9.]*]] = private {{.*}}constant [3 x i64] [i64 35, i64 35, i64 35] +// HOST: @[[MAPTYPES_ARRAY_R1:.offload_maptypes[0-9.]*]] = private {{.*}}constant [3 x i64] [i64 33, i64 33, i64 33] +// HOST-INT128: @[[MAPTYPES_INT128_R0:.offload_maptypes[0-9.]*]] = private {{.*}}constant [3 x i64] [i64 35, i64 35, i64 35] +// HOST-INT128: @[[MAPTYPES_INT128_R1:.offload_maptypes[0-9.]*]] = private {{.*}}constant [3 x i64] [i64 34, i64 34, i64 34] // // CHECK: @.omp_offloading.entry_name{{[0-9.]*}} = {{.*}} c"[[OFFLOAD_PRIVATE:__omp_offloading_[^"\\]*mapWithPrivate[^"\\]*]]\00" // CHECK: @.omp_offloading.entry_name{{[0-9.]*}} = {{.*}} c"[[OFFLOAD_FIRSTPRIVATE:__omp_offloading_[^"\\]*mapWithFirstprivate[^"\\]*]]\00" @@ -42,9 +43,7 @@ // INT128: @.omp_offloading.entry_name{{[0-9.]*}} = {{.*}} c"[[OFFLOAD_INT128_R1:__omp_offloading_[^"\\]*mapInt128[^"\\]*]]\00" // HOST: define {{.*}}mapWithPrivate -// HOST: call {{.*}} @.[[OFFLOAD_PRIVATE]].region_id -// HOST-NOT: offload_maptypes -// HOST-SAME: {{$}} +// HOST: call {{.*}} @.[[OFFLOAD_PRIVATE]].region_id{{.*}} @[[MAPTYPES_PRIVATE]] // // CHECK: define {{.*}} void @[[OFFLOAD_PRIVATE]]() // CHECK: call void ({{.*}}@[[OUTLINE_PRIVATE:.omp_outlined.[.0-9]*]] From 6d247f980d922055018137c0d1400fde83d9449f Mon Sep 17 00:00:00 2001 From: Chen Zheng Date: Wed, 15 Jul 2020 04:03:35 -0400 Subject: [PATCH 701/771] [SCEV][IndVarSimplify] insert point should not be block front. Recommit after removing the unused cast instructions. Differential Revision: https://reviews.llvm.org/D80975 --- llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 15 ++++++++++-- .../Utils/ScalarEvolutionExpander.cpp | 14 +++++------ .../IndVarSimplify/widen-i32-i8ptr.ll | 24 +++++++++++++++++++ 3 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 llvm/test/Transforms/IndVarSimplify/widen-i32-i8ptr.ll diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index 0f36c3f772e65..51d12faf712ad 100644 --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -1435,8 +1435,19 @@ PHINode *WidenIV::createWideIV(SCEVExpander &Rewriter) { // either find an existing phi or materialize a new one. Either way, we // expect a well-formed cyclic phi-with-increments. i.e. any operand not part // of the phi-SCC dominates the loop entry. - Instruction *InsertPt = &L->getHeader()->front(); - WidePhi = cast(Rewriter.expandCodeFor(AddRec, WideType, InsertPt)); + Instruction *InsertPt = &*L->getHeader()->getFirstInsertionPt(); + Value *ExpandInst = Rewriter.expandCodeFor(AddRec, WideType, InsertPt); + // If the wide phi is not a phi node, for example a cast node, like bitcast, + // inttoptr, ptrtoint, just skip for now. + if (!(WidePhi = dyn_cast(ExpandInst))) { + // if the cast node is an inserted instruction without any user, we should + // remove it to make sure the pass don't touch the function as we can not + // wide the phi. + if (ExpandInst->hasNUses(0) && + Rewriter.isInsertedInstruction(cast(ExpandInst))) + DeadInsts.emplace_back(ExpandInst); + return nullptr; + } // Remembering the WideIV increment generated by SCEVExpander allows // widenIVUse to reuse it when widening the narrow IV's increment. We don't diff --git a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp index 71b48482f26aa..c54ae26b53234 100644 --- a/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp +++ b/llvm/lib/Transforms/Utils/ScalarEvolutionExpander.cpp @@ -1292,7 +1292,8 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, if (useSubtract) Step = SE.getNegativeSCEV(Step); // Expand the step somewhere that dominates the loop header. - Value *StepV = expandCodeFor(Step, IntTy, &L->getHeader()->front()); + Value *StepV = expandCodeFor(Step, IntTy, + &*L->getHeader()->getFirstInsertionPt()); // The no-wrap behavior proved by IsIncrement(NUW|NSW) is only applicable if // we actually do emit an addition. It does not apply if we emit a @@ -1438,7 +1439,8 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { { // Expand the step somewhere that dominates the loop header. SCEVInsertPointGuard Guard(Builder, this); - StepV = expandCodeFor(Step, IntTy, &L->getHeader()->front()); + StepV = expandCodeFor(Step, IntTy, + &*L->getHeader()->getFirstInsertionPt()); } Result = expandIVInc(PN, StepV, L, ExpandTy, IntTy, useSubtract); } @@ -1870,11 +1872,6 @@ Value *SCEVExpander::expand(const SCEV *S) { } } - // IndVarSimplify sometimes sets the insertion point at the block start, even - // when there are PHIs at that point. We must correct for this. - if (isa(*InsertPt)) - InsertPt = &*InsertPt->getParent()->getFirstInsertionPt(); - // Check to see if we already expanded this here. auto I = InsertedExpressions.find(std::make_pair(S, InsertPt)); if (I != InsertedExpressions.end()) @@ -1945,7 +1942,8 @@ SCEVExpander::getOrInsertCanonicalInductionVariable(const Loop *L, // Emit code for it. SCEVInsertPointGuard Guard(Builder, this); PHINode *V = - cast(expandCodeFor(H, nullptr, &L->getHeader()->front())); + cast(expandCodeFor(H, nullptr, + &*L->getHeader()->getFirstInsertionPt())); return V; } diff --git a/llvm/test/Transforms/IndVarSimplify/widen-i32-i8ptr.ll b/llvm/test/Transforms/IndVarSimplify/widen-i32-i8ptr.ll new file mode 100644 index 0000000000000..80191d4e5b771 --- /dev/null +++ b/llvm/test/Transforms/IndVarSimplify/widen-i32-i8ptr.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -indvars -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-n32:64" + +define dso_local void @Widen_i32_i8ptr() local_unnamed_addr { +; CHECK-LABEL: @Widen_i32_i8ptr( +; CHECK: phi i8* +; CHECK: phi i32 +entry: + %ptrids = alloca [15 x i8*], align 8 + %arraydecay2032 = getelementptr inbounds [15 x i8*], [15 x i8*]* %ptrids, i64 0, i64 0 + store i8** %arraydecay2032, i8*** inttoptr (i64 8 to i8***), align 8 + br label %for.cond2106 + +for.cond2106: ; preds = %for.cond2106, %entry + %gid.0 = phi i8* [ null, %entry ], [ %incdec.ptr, %for.cond2106 ] + %i.0 = phi i32 [ 0, %entry ], [ %inc2117, %for.cond2106 ] + %incdec.ptr = getelementptr inbounds i8, i8* %gid.0, i64 1 + %idxprom2114 = zext i32 %i.0 to i64 + %arrayidx2115 = getelementptr inbounds [15 x i8*], [15 x i8*]* %ptrids, i64 0, i64 %idxprom2114 + store i8* %gid.0, i8** %arrayidx2115, align 8 + %inc2117 = add nuw nsw i32 %i.0, 1 + br label %for.cond2106 +} From bb07eb944f9b9ca7b3d8ac786c92e1f5bf59e3e1 Mon Sep 17 00:00:00 2001 From: Chen Zheng Date: Fri, 17 Jul 2020 22:51:00 -0400 Subject: [PATCH 702/771] [PowerPC]add testcase for adding store (load float*) pattern, nfc --- .../SimplifyCFG/PowerPC/prefer-load-i32.ll | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 llvm/test/Transforms/SimplifyCFG/PowerPC/prefer-load-i32.ll diff --git a/llvm/test/Transforms/SimplifyCFG/PowerPC/prefer-load-i32.ll b/llvm/test/Transforms/SimplifyCFG/PowerPC/prefer-load-i32.ll new file mode 100644 index 0000000000000..943fcba57c654 --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/PowerPC/prefer-load-i32.ll @@ -0,0 +1,33 @@ +; RUN: opt < %s -mtriple=powerpc64le-unknown-linux-gnu -simplifycfg -S | \ +; RUN: FileCheck %s + +define float @foo(float* %src, float* %dest, i32 signext %count, i32 signext %cond) { +; CHECK-LABEL: @foo( +; CHECK-LABEL: entry: +; CHECK: %0 = load float, float* %arrayidx, align 4 +entry: + %cmp = icmp sgt i32 %cond, 10 + %idxprom = sext i32 %count to i64 + %arrayidx = getelementptr inbounds float, float* %src, i64 %idxprom + br i1 %cmp, label %if.then, label %if.else + +; CHECK-LABEL: if.then: +; CHECK-NOT: load float +if.then: ; preds = %entry + %0 = load float, float* %arrayidx, align 4 + %res = fmul float %0, 3.000000e+00 + br label %if.end + +; CHECK-LABEL: if.else: +; CHECK-NOT: load float +if.else: ; preds = %entry + %1 = load float, float* %arrayidx, align 4 + %idxprom3 = sext i32 %count to i64 + %arrayidx4 = getelementptr inbounds float, float* %dest, i64 %idxprom3 + store float %1, float* %arrayidx4, align 4 + br label %if.end + +if.end: ; preds = %if.else, %if.then + %res2.0 = phi float [ %res, %if.then ], [ 0.000000e+00, %if.else ] + ret float %res2.0 +} From 780528d9da707b15849d6c9711cc3ab19f6c7f00 Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Sat, 18 Jul 2020 03:09:39 +0000 Subject: [PATCH 703/771] sanitizers: Implement sig{and,or}set interceptors Also adds a sanitizers-wide test, and a msan test, for these functions. --- .../sanitizer_common_interceptors.inc | 28 +++++++ .../sanitizer_platform_interceptors.h | 1 + compiler-rt/test/msan/Linux/sigandorset.cpp | 27 +++++++ .../TestCases/Linux/signal_send.cpp | 75 +++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 compiler-rt/test/msan/Linux/sigandorset.cpp create mode 100644 compiler-rt/test/sanitizer_common/TestCases/Linux/signal_send.cpp diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index d7e0bba762941..0fdaf00e67c17 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -4085,6 +4085,33 @@ INTERCEPTOR(int, sigfillset, __sanitizer_sigset_t *set) { #define INIT_SIGSETOPS #endif +#if SANITIZER_INTERCEPT_SIGSET_LOGICOPS +INTERCEPTOR(int, sigandset, __sanitizer_sigset_t *dst, __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sigandset, dst, src1, src2); + if (src1) COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1)); + if (src2) COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2)); + int res = REAL(sigandset)(dst, src1, src2); + if (!res && dst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst)); + return res; +} + +INTERCEPTOR(int, sigorset, __sanitizer_sigset_t *dst, __sanitizer_sigset_t *src1, __sanitizer_sigset_t *src2) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, sigorset, dst, src1, src2); + if (src1) COMMON_INTERCEPTOR_READ_RANGE(ctx, src1, sizeof(*src1)); + if (src2) COMMON_INTERCEPTOR_READ_RANGE(ctx, src2, sizeof(*src2)); + int res = REAL(sigorset)(dst, src1, src2); + if (!res && dst) COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, sizeof(*dst)); + return res; +} +#define INIT_SIGSET_LOGICOPS \ + COMMON_INTERCEPT_FUNCTION(sigandset); \ + COMMON_INTERCEPT_FUNCTION(sigorset); +#else +#define INIT_SIGSET_LOGICOPS +#endif + #if SANITIZER_INTERCEPT_SIGPENDING INTERCEPTOR(int, sigpending, __sanitizer_sigset_t *set) { void *ctx; @@ -9996,6 +10023,7 @@ static void InitializeCommonInterceptors() { INIT_SIGWAITINFO; INIT_SIGTIMEDWAIT; INIT_SIGSETOPS; + INIT_SIGSET_LOGICOPS; INIT_SIGPENDING; INIT_SIGPROCMASK; INIT_PTHREAD_SIGMASK; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index e28bb937ae83d..04b61d6daae78 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -333,6 +333,7 @@ #define SANITIZER_INTERCEPT_SIGTIMEDWAIT SI_LINUX_NOT_ANDROID || SI_SOLARIS #define SANITIZER_INTERCEPT_SIGSETOPS \ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) +#define SANITIZER_INTERCEPT_SIGSET_LOGICOPS SI_LINUX_NOT_ANDROID #define SANITIZER_INTERCEPT_SIGPENDING SI_POSIX #define SANITIZER_INTERCEPT_SIGPROCMASK SI_POSIX #define SANITIZER_INTERCEPT_PTHREAD_SIGMASK SI_POSIX diff --git a/compiler-rt/test/msan/Linux/sigandorset.cpp b/compiler-rt/test/msan/Linux/sigandorset.cpp new file mode 100644 index 0000000000000..d0e552fcfa019 --- /dev/null +++ b/compiler-rt/test/msan/Linux/sigandorset.cpp @@ -0,0 +1,27 @@ +// RUN: %clangxx_msan -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_msan -DLEFT_OK -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_msan -DRIGHT_OK -std=c++11 -O0 -g %s -o %t && not %run %t 2<&1 | FileCheck %s +// RUN: %clangxx_msan -DLEFT_OK -DRIGHT_OK -std=c++11 -O0 -g %s -o %t && %run %t + +#include +#include +#include +#include +#include + +int main(void) { + sigset_t s, t, u; +#ifdef LEFT_OK + sigemptyset(&t); +#endif +#ifdef RIGHT_OK + sigemptyset(&u); +#endif + + // CHECK: MemorySanitizer: use-of-uninitialized-value + // CHECK-NEXT: in main {{.*}}sigandorset.cpp:[[@LINE+1]] + sigandset(&s, &t, &u); + sigorset(&s, &t, &u); + __msan_check_mem_is_initialized(&s, sizeof s); + return 0; +} diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_send.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_send.cpp new file mode 100644 index 0000000000000..54014da8b532a --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_send.cpp @@ -0,0 +1,75 @@ +// RUN: %clangxx -std=c++11 -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include +#include +#include + +sigset_t mkset(int n, ...) { + sigset_t s; + int res = 0; + res |= sigemptyset(&s); + va_list va; + va_start(va, n); + while (n--) { + res |= sigaddset(&s, va_arg(va, int)); + } + va_end(va); + assert(!res); + return s; +} + +sigset_t sigset_or(sigset_t first, sigset_t second) { + sigset_t out; + int res = sigorset(&out, &first, &second); + assert(!res); + return out; +} + +sigset_t sigset_and(sigset_t first, sigset_t second) { + sigset_t out; + int res = sigandset(&out, &first, &second); + assert(!res); + return out; +} + +int fork_and_signal(sigset_t s) { + if (pid_t pid = fork()) { + kill(pid, SIGUSR1); + kill(pid, SIGUSR2); + int child_stat; + wait(&child_stat); + return !WIFEXITED(child_stat); + } else { + int sig; + int res = sigwait(&s, &sig); + assert(!res); + fprintf(stderr, "died with sig %d\n", sig); + _exit(0); + } +} + +void test_sigwait() { + // test sigorset... s should now contain SIGUSR1 | SIGUSR2 + sigset_t s = sigset_or(mkset(1, SIGUSR1), mkset(1, SIGUSR2)); + sigprocmask(SIG_BLOCK, &s, 0); + int res; + res = fork_and_signal(s); + fprintf(stderr, "fork_and_signal with SIGUSR1,2: %d\n", res); + // CHECK: died with sig 10 + // CHECK: fork_and_signal with SIGUSR1,2: 0 + + // test sigandset... s should only have SIGUSR2 now + s = sigset_and(s, mkset(1, SIGUSR2)); + res = fork_and_signal(s); + fprintf(stderr, "fork_and_signal with SIGUSR2: %d\n", res); + // CHECK: died with sig 12 + // CHECK: fork_and_signal with SIGUSR2: 0 +} + +int main(void) { + test_sigwait(); + return 0; +} From c42509413f69667361e93b5834fe368bfa4a6e82 Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Sat, 18 Jul 2020 03:18:48 +0000 Subject: [PATCH 704/771] [LLVM] Add libatomic load/store functions to TargetLibraryInfo This allows treating these functions like libcalls. This patch is a prerequisite to instrumenting them in MSAN: https://reviews.llvm.org/D83337 Differential Revision: https://reviews.llvm.org/D83361 --- llvm/include/llvm/Analysis/TargetLibraryInfo.def | 6 ++++++ llvm/lib/Analysis/TargetLibraryInfo.cpp | 9 +++++++++ llvm/unittests/Analysis/TargetLibraryInfoTest.cpp | 3 +++ 3 files changed, 18 insertions(+) diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def index 3864d4955104b..36b39f4a0e231 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -262,6 +262,12 @@ TLI_DEFINE_STRING_INTERNAL("__atanhf_finite") /// long double __atanhl_finite(long double x); TLI_DEFINE_ENUM_INTERNAL(atanhl_finite) TLI_DEFINE_STRING_INTERNAL("__atanhl_finite") +/// void __atomic_load(size_t size, void *mptr, void *vptr, int smodel); +TLI_DEFINE_ENUM_INTERNAL(atomic_load) +TLI_DEFINE_STRING_INTERNAL("__atomic_load") +/// void __atomic_store(size_t size, void *mptr, void *vptr, int smodel); +TLI_DEFINE_ENUM_INTERNAL(atomic_store) +TLI_DEFINE_STRING_INTERNAL("__atomic_store") /// double __cosh_finite(double x); TLI_DEFINE_ENUM_INTERNAL(cosh_finite) TLI_DEFINE_STRING_INTERNAL("__cosh_finite") diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 60cfb04634c4a..0b465d3c31773 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -1228,6 +1228,15 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, case LibFunc_ZdaPvmSt11align_val_t: return (NumParams == 3 && FTy.getParamType(0)->isPointerTy()); + // void __atomic_load(size_t, void *, void *, int) + case LibFunc_atomic_load: + // void __atomic_store(size_t, void *, void *, int) + case LibFunc_atomic_store: + return (NumParams == 4 && FTy.getParamType(0)->isIntegerTy() && + FTy.getParamType(1)->isPointerTy() && + FTy.getParamType(2)->isPointerTy() && + FTy.getParamType(3)->isIntegerTy()); + case LibFunc_memset_pattern16: return (!FTy.isVarArg() && NumParams == 3 && FTy.getParamType(0)->isPointerTy() && diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp index 83637596282e2..db75192640def 100644 --- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp +++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp @@ -495,6 +495,9 @@ TEST_F(TargetLibraryInfoTest, ValidProto) { "declare i8* @mempcpy(i8*, i8*, i64)\n" "declare i8* @memrchr(i8*, i32, i64)\n" + "declare void @__atomic_load(i64, i8*, i8*, i32)\n" + "declare void @__atomic_store(i64, i8*, i8*, i32)\n" + // These are similar to the FILE* fgetc/fputc. "declare i32 @_IO_getc(%struct*)\n" "declare i32 @_IO_putc(i32, %struct*)\n" From 1f29171ae77f81cacea32808b67d7ae62da23e0c Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Sat, 18 Jul 2020 03:39:14 +0000 Subject: [PATCH 705/771] update libatomic instrumentation --- compiler-rt/test/msan/libatomic.c | 37 ++++++ .../Instrumentation/MemorySanitizer.cpp | 113 ++++++++++++++++++ .../MemorySanitizer/libatomic.ll | 70 +++++++++++ 3 files changed, 220 insertions(+) create mode 100644 compiler-rt/test/msan/libatomic.c create mode 100644 llvm/test/Instrumentation/MemorySanitizer/libatomic.ll diff --git a/compiler-rt/test/msan/libatomic.c b/compiler-rt/test/msan/libatomic.c new file mode 100644 index 0000000000000..b230a0972c6db --- /dev/null +++ b/compiler-rt/test/msan/libatomic.c @@ -0,0 +1,37 @@ +// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -latomic -DTEST_STORE -O0 %s -o %t && %run %t 2>&1 +// RUN: %clangxx_msan -fsanitize-memory-track-origins=0 -latomic -DTEST_LOAD -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK +// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -latomic -DTEST_LOAD -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SHADOW + +#include +#include + +typedef struct __attribute((packed)) { + uint8_t val[3]; +} i24; + +void copy(i24 *dst, i24 *src); + +int main() { + i24 uninit; + i24 init = {0}; + + __msan_check_mem_is_initialized(&init, 3); + copy(&init, &uninit); + __msan_check_mem_is_initialized(&init, 3); +} + +void copy(i24 *dst, i24 *src) { +#ifdef TEST_LOAD + __atomic_load(src, dst, __ATOMIC_RELAXED); + + // CHECK: MemorySanitizer: use-of-uninitialized-value + // CHECK: #0 {{0x[a-f0-9]+}} in main{{.*}}libatomic.c:[[@LINE-8]] + + // CHECK-SHADOW: Uninitialized value was stored to memory at + // CHECK-SHADOW: #0 {{0x[a-f0-9]+}} in copy{{.*}}libatomic.c:[[@LINE-6]] +#endif +#ifdef TEST_STORE + // Store always writes a clean shadow + __atomic_store(src, dst, __ATOMIC_RELAXED); +#endif +} diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index fcf7f470b3e10..0001559c4051d 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -572,6 +572,9 @@ class MemorySanitizer { /// uninitialized value and returns an updated origin id encoding this info. FunctionCallee MsanChainOriginFn; + /// Run-time helper that paints an origin over a region. + FunctionCallee MsanSetOriginFn; + /// MSan runtime replacements for memmove, memcpy and memset. FunctionCallee MemmoveFn, MemcpyFn, MemsetFn; @@ -850,6 +853,9 @@ void MemorySanitizer::initializeCallbacks(Module &M) { // instrumentation. MsanChainOriginFn = M.getOrInsertFunction( "__msan_chain_origin", IRB.getInt32Ty(), IRB.getInt32Ty()); + MsanSetOriginFn = + M.getOrInsertFunction("__msan_set_origin", IRB.getVoidTy(), + IRB.getInt8PtrTy(), IntptrTy, IRB.getInt32Ty()); MemmoveFn = M.getOrInsertFunction( "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy); @@ -1769,6 +1775,24 @@ struct MemorySanitizerVisitor : public InstVisitor { llvm_unreachable("Unknown ordering"); } + Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB) { + constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1; + uint32_t OrderingTable[NumOrderings] = {}; + + OrderingTable[(int)AtomicOrderingCABI::relaxed] = + OrderingTable[(int)AtomicOrderingCABI::release] = + (int)AtomicOrderingCABI::release; + OrderingTable[(int)AtomicOrderingCABI::consume] = + OrderingTable[(int)AtomicOrderingCABI::acquire] = + OrderingTable[(int)AtomicOrderingCABI::acq_rel] = + (int)AtomicOrderingCABI::acq_rel; + OrderingTable[(int)AtomicOrderingCABI::seq_cst] = + (int)AtomicOrderingCABI::seq_cst; + + return ConstantDataVector::get(IRB.getContext(), + makeArrayRef(OrderingTable, NumOrderings)); + } + AtomicOrdering addAcquireOrdering(AtomicOrdering a) { switch (a) { case AtomicOrdering::NotAtomic: @@ -1786,6 +1810,24 @@ struct MemorySanitizerVisitor : public InstVisitor { llvm_unreachable("Unknown ordering"); } + Value *makeAddAcquireOrderingTable(IRBuilder<> &IRB) { + constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1; + uint32_t OrderingTable[NumOrderings] = {}; + + OrderingTable[(int)AtomicOrderingCABI::relaxed] = + OrderingTable[(int)AtomicOrderingCABI::acquire] = + OrderingTable[(int)AtomicOrderingCABI::consume] = + (int)AtomicOrderingCABI::acquire; + OrderingTable[(int)AtomicOrderingCABI::release] = + OrderingTable[(int)AtomicOrderingCABI::acq_rel] = + (int)AtomicOrderingCABI::acq_rel; + OrderingTable[(int)AtomicOrderingCABI::seq_cst] = + (int)AtomicOrderingCABI::seq_cst; + + return ConstantDataVector::get(IRB.getContext(), + makeArrayRef(OrderingTable, NumOrderings)); + } + // ------------------- Visitors. using InstVisitor::visit; void visit(Instruction &I) { @@ -3404,6 +3446,60 @@ struct MemorySanitizerVisitor : public InstVisitor { } } + void visitLibAtomicLoad(CallBase &CB) { + IRBuilder<> IRB(&CB); + Value *Size = CB.getArgOperand(0); + Value *SrcPtr = CB.getArgOperand(1); + Value *DstPtr = CB.getArgOperand(2); + Value *Ordering = CB.getArgOperand(3); + // Convert the call to have at least Acquire ordering to make sure + // the shadow operations aren't reordered before it. + Value *NewOrdering = + IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering); + CB.setArgOperand(3, NewOrdering); + + IRBuilder<> NextIRB(CB.getNextNode()); + NextIRB.SetCurrentDebugLocation(CB.getDebugLoc()); + + Value *SrcShadowPtr, *SrcOriginPtr; + std::tie(SrcShadowPtr, SrcOriginPtr) = + getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(), Align(1), + /*isStore*/ false); + Value *DstShadowPtr = + getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(), Align(1), + /*isStore*/ true) + .first; + + NextIRB.CreateMemCpy(DstShadowPtr, Align(1), SrcShadowPtr, Align(1), Size); + if (MS.TrackOrigins) { + Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr, + kMinOriginAlignment); + Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB); + NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin}); + } + } + + void visitLibAtomicStore(CallBase &CB) { + IRBuilder<> IRB(&CB); + Value *Size = CB.getArgOperand(0); + Value *DstPtr = CB.getArgOperand(2); + Value *Ordering = CB.getArgOperand(3); + // Convert the call to have at least Release ordering to make sure + // the shadow operations aren't reordered after it. + Value *NewOrdering = + IRB.CreateExtractElement(makeAddReleaseOrderingTable(IRB), Ordering); + CB.setArgOperand(3, NewOrdering); + + Value *DstShadowPtr = + getShadowOriginPtr(DstPtr, IRB, IRB.getInt8Ty(), Align(1), + /*isStore*/ true) + .first; + + // Atomic store always paints clean shadow/origin. See file header. + IRB.CreateMemSet(DstShadowPtr, getCleanShadow(IRB.getInt8Ty()), Size, + Align(1)); + } + void visitCallBase(CallBase &CB) { assert(!CB.getMetadata("nosanitize")); if (CB.isInlineAsm()) { @@ -3417,6 +3513,23 @@ struct MemorySanitizerVisitor : public InstVisitor { visitInstruction(CB); return; } + LibFunc LF; + if (TLI->getLibFunc(CB, LF)) { + // libatomic.a functions need to have special handling because there isn't + // a good way to intercept them or compile the library with + // instrumentation. + switch (LF) { + case LibFunc_atomic_load: + visitLibAtomicLoad(CB); + return; + case LibFunc_atomic_store: + visitLibAtomicStore(CB); + return; + default: + break; + } + } + if (auto *Call = dyn_cast(&CB)) { assert(!isa(Call) && "intrinsics are handled elsewhere"); diff --git a/llvm/test/Instrumentation/MemorySanitizer/libatomic.ll b/llvm/test/Instrumentation/MemorySanitizer/libatomic.ll new file mode 100644 index 0000000000000..a2515740b4591 --- /dev/null +++ b/llvm/test/Instrumentation/MemorySanitizer/libatomic.ll @@ -0,0 +1,70 @@ +; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck %s +; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S -passes=msan 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-ORIGIN +; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +declare void @__atomic_load(i64, i8*, i8*, i32) +declare void @__atomic_store(i64, i8*, i8*, i32) + +define i24 @odd_sized_load(i24* %ptr) sanitize_memory { +; CHECK: @odd_sized_load(i24* {{.*}}[[PTR:%.+]]) +; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1 +; CHECK-ORIGIN: @__msan_set_alloca_origin +; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8* +; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8* +; CHECK: call void @__atomic_load(i64 3, i8* [[PTR_I8]], i8* [[VAL_PTR_I8]], i32 2) + +; CHECK: ptrtoint i8* [[PTR_I8]] +; CHECK: xor +; CHECK: [[SPTR_I8:%.*]] = inttoptr +; CHECK-ORIGIN: add +; CHECK-ORIGIN: and +; CHECK-ORIGIN: [[OPTR:%.*]] = inttoptr + +; CHECK: ptrtoint i8* [[VAL_PTR_I8]] +; CHECK: xor +; CHECK: [[VAL_SPTR_I8:%.*]] = inttoptr +; CHECK-ORIGIN: add +; CHECK-ORIGIN: and +; CHECK-ORIGIN: [[VAL_OPTR:%.*]] = inttoptr + +; CHECK: call void @llvm.memcpy{{.*}}(i8* align 1 [[VAL_SPTR_I8]], i8* align 1 [[SPTR_I8]], i64 3 + +; CHECK-ORIGIN: [[ARG_ORIGIN:%.*]] = load i32, i32* [[OPTR]] +; CHECK-ORIGIN: [[VAL_ORIGIN:%.*]] = call i32 @__msan_chain_origin(i32 [[ARG_ORIGIN]]) +; CHECK-ORIGIN: call void @__msan_set_origin(i8* [[VAL_PTR_I8]], i64 3, i32 [[VAL_ORIGIN]]) + +; CHECK: [[VAL:%.*]] = load i24, i24* [[VAL_PTR]] +; CHECK: ret i24 [[VAL]] + %val_ptr = alloca i24, align 1 + %val_ptr_i8 = bitcast i24* %val_ptr to i8* + %ptr_i8 = bitcast i24* %ptr to i8* + call void @__atomic_load(i64 3, i8* %ptr_i8, i8* %val_ptr_i8, i32 0) + %val = load i24, i24* %val_ptr + ret i24 %val +} + +define void @odd_sized_store(i24* %ptr, i24 %val) sanitize_memory { +; CHECK: @odd_sized_store(i24* {{.*}}[[PTR:%.+]], i24 {{.*}}[[VAL:%.+]]) +; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1 +; CHECK: store i24 [[VAL]], i24* [[VAL_PTR]] +; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8* +; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8* + +; CHECK: ptrtoint i8* [[PTR_I8]] +; CHECK: xor +; CHECK: [[SPTR_I8:%.*]] = inttoptr +; CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[SPTR_I8]], i8 0, i64 3 +; CHECK-ORIGIN: call void @__msan_set_origin(i8* [[PTR_I8]], i64 3, i32 0) + +; CHECK: call void @__atomic_store(i64 3, i8* [[VAL_PTR_I8]], i8* [[PTR_I8]], i32 3) +; CHECK: ret void + %val_ptr = alloca i24, align 1 + store i24 %val, i24* %val_ptr + %val_ptr_i8 = bitcast i24* %val_ptr to i8* + %ptr_i8 = bitcast i24* %ptr to i8* + call void @__atomic_store(i64 3, i8* %val_ptr_i8, i8* %ptr_i8, i32 0) + ret void +} + From 951584db4ffbc8e8cfe954134edfee9974e8ae28 Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Sat, 18 Jul 2020 03:53:00 +0000 Subject: [PATCH 706/771] Revert "update libatomic instrumentation" This was committed mistakenly. This reverts commit 1f29171ae77f81cacea32808b67d7ae62da23e0c. --- compiler-rt/test/msan/libatomic.c | 37 ------ .../Instrumentation/MemorySanitizer.cpp | 113 ------------------ .../MemorySanitizer/libatomic.ll | 70 ----------- 3 files changed, 220 deletions(-) delete mode 100644 compiler-rt/test/msan/libatomic.c delete mode 100644 llvm/test/Instrumentation/MemorySanitizer/libatomic.ll diff --git a/compiler-rt/test/msan/libatomic.c b/compiler-rt/test/msan/libatomic.c deleted file mode 100644 index b230a0972c6db..0000000000000 --- a/compiler-rt/test/msan/libatomic.c +++ /dev/null @@ -1,37 +0,0 @@ -// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -latomic -DTEST_STORE -O0 %s -o %t && %run %t 2>&1 -// RUN: %clangxx_msan -fsanitize-memory-track-origins=0 -latomic -DTEST_LOAD -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK -// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -latomic -DTEST_LOAD -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-SHADOW - -#include -#include - -typedef struct __attribute((packed)) { - uint8_t val[3]; -} i24; - -void copy(i24 *dst, i24 *src); - -int main() { - i24 uninit; - i24 init = {0}; - - __msan_check_mem_is_initialized(&init, 3); - copy(&init, &uninit); - __msan_check_mem_is_initialized(&init, 3); -} - -void copy(i24 *dst, i24 *src) { -#ifdef TEST_LOAD - __atomic_load(src, dst, __ATOMIC_RELAXED); - - // CHECK: MemorySanitizer: use-of-uninitialized-value - // CHECK: #0 {{0x[a-f0-9]+}} in main{{.*}}libatomic.c:[[@LINE-8]] - - // CHECK-SHADOW: Uninitialized value was stored to memory at - // CHECK-SHADOW: #0 {{0x[a-f0-9]+}} in copy{{.*}}libatomic.c:[[@LINE-6]] -#endif -#ifdef TEST_STORE - // Store always writes a clean shadow - __atomic_store(src, dst, __ATOMIC_RELAXED); -#endif -} diff --git a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp index 0001559c4051d..fcf7f470b3e10 100644 --- a/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -572,9 +572,6 @@ class MemorySanitizer { /// uninitialized value and returns an updated origin id encoding this info. FunctionCallee MsanChainOriginFn; - /// Run-time helper that paints an origin over a region. - FunctionCallee MsanSetOriginFn; - /// MSan runtime replacements for memmove, memcpy and memset. FunctionCallee MemmoveFn, MemcpyFn, MemsetFn; @@ -853,9 +850,6 @@ void MemorySanitizer::initializeCallbacks(Module &M) { // instrumentation. MsanChainOriginFn = M.getOrInsertFunction( "__msan_chain_origin", IRB.getInt32Ty(), IRB.getInt32Ty()); - MsanSetOriginFn = - M.getOrInsertFunction("__msan_set_origin", IRB.getVoidTy(), - IRB.getInt8PtrTy(), IntptrTy, IRB.getInt32Ty()); MemmoveFn = M.getOrInsertFunction( "__msan_memmove", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IntptrTy); @@ -1775,24 +1769,6 @@ struct MemorySanitizerVisitor : public InstVisitor { llvm_unreachable("Unknown ordering"); } - Value *makeAddReleaseOrderingTable(IRBuilder<> &IRB) { - constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1; - uint32_t OrderingTable[NumOrderings] = {}; - - OrderingTable[(int)AtomicOrderingCABI::relaxed] = - OrderingTable[(int)AtomicOrderingCABI::release] = - (int)AtomicOrderingCABI::release; - OrderingTable[(int)AtomicOrderingCABI::consume] = - OrderingTable[(int)AtomicOrderingCABI::acquire] = - OrderingTable[(int)AtomicOrderingCABI::acq_rel] = - (int)AtomicOrderingCABI::acq_rel; - OrderingTable[(int)AtomicOrderingCABI::seq_cst] = - (int)AtomicOrderingCABI::seq_cst; - - return ConstantDataVector::get(IRB.getContext(), - makeArrayRef(OrderingTable, NumOrderings)); - } - AtomicOrdering addAcquireOrdering(AtomicOrdering a) { switch (a) { case AtomicOrdering::NotAtomic: @@ -1810,24 +1786,6 @@ struct MemorySanitizerVisitor : public InstVisitor { llvm_unreachable("Unknown ordering"); } - Value *makeAddAcquireOrderingTable(IRBuilder<> &IRB) { - constexpr int NumOrderings = (int)AtomicOrderingCABI::seq_cst + 1; - uint32_t OrderingTable[NumOrderings] = {}; - - OrderingTable[(int)AtomicOrderingCABI::relaxed] = - OrderingTable[(int)AtomicOrderingCABI::acquire] = - OrderingTable[(int)AtomicOrderingCABI::consume] = - (int)AtomicOrderingCABI::acquire; - OrderingTable[(int)AtomicOrderingCABI::release] = - OrderingTable[(int)AtomicOrderingCABI::acq_rel] = - (int)AtomicOrderingCABI::acq_rel; - OrderingTable[(int)AtomicOrderingCABI::seq_cst] = - (int)AtomicOrderingCABI::seq_cst; - - return ConstantDataVector::get(IRB.getContext(), - makeArrayRef(OrderingTable, NumOrderings)); - } - // ------------------- Visitors. using InstVisitor::visit; void visit(Instruction &I) { @@ -3446,60 +3404,6 @@ struct MemorySanitizerVisitor : public InstVisitor { } } - void visitLibAtomicLoad(CallBase &CB) { - IRBuilder<> IRB(&CB); - Value *Size = CB.getArgOperand(0); - Value *SrcPtr = CB.getArgOperand(1); - Value *DstPtr = CB.getArgOperand(2); - Value *Ordering = CB.getArgOperand(3); - // Convert the call to have at least Acquire ordering to make sure - // the shadow operations aren't reordered before it. - Value *NewOrdering = - IRB.CreateExtractElement(makeAddAcquireOrderingTable(IRB), Ordering); - CB.setArgOperand(3, NewOrdering); - - IRBuilder<> NextIRB(CB.getNextNode()); - NextIRB.SetCurrentDebugLocation(CB.getDebugLoc()); - - Value *SrcShadowPtr, *SrcOriginPtr; - std::tie(SrcShadowPtr, SrcOriginPtr) = - getShadowOriginPtr(SrcPtr, NextIRB, NextIRB.getInt8Ty(), Align(1), - /*isStore*/ false); - Value *DstShadowPtr = - getShadowOriginPtr(DstPtr, NextIRB, NextIRB.getInt8Ty(), Align(1), - /*isStore*/ true) - .first; - - NextIRB.CreateMemCpy(DstShadowPtr, Align(1), SrcShadowPtr, Align(1), Size); - if (MS.TrackOrigins) { - Value *SrcOrigin = NextIRB.CreateAlignedLoad(MS.OriginTy, SrcOriginPtr, - kMinOriginAlignment); - Value *NewOrigin = updateOrigin(SrcOrigin, NextIRB); - NextIRB.CreateCall(MS.MsanSetOriginFn, {DstPtr, Size, NewOrigin}); - } - } - - void visitLibAtomicStore(CallBase &CB) { - IRBuilder<> IRB(&CB); - Value *Size = CB.getArgOperand(0); - Value *DstPtr = CB.getArgOperand(2); - Value *Ordering = CB.getArgOperand(3); - // Convert the call to have at least Release ordering to make sure - // the shadow operations aren't reordered after it. - Value *NewOrdering = - IRB.CreateExtractElement(makeAddReleaseOrderingTable(IRB), Ordering); - CB.setArgOperand(3, NewOrdering); - - Value *DstShadowPtr = - getShadowOriginPtr(DstPtr, IRB, IRB.getInt8Ty(), Align(1), - /*isStore*/ true) - .first; - - // Atomic store always paints clean shadow/origin. See file header. - IRB.CreateMemSet(DstShadowPtr, getCleanShadow(IRB.getInt8Ty()), Size, - Align(1)); - } - void visitCallBase(CallBase &CB) { assert(!CB.getMetadata("nosanitize")); if (CB.isInlineAsm()) { @@ -3513,23 +3417,6 @@ struct MemorySanitizerVisitor : public InstVisitor { visitInstruction(CB); return; } - LibFunc LF; - if (TLI->getLibFunc(CB, LF)) { - // libatomic.a functions need to have special handling because there isn't - // a good way to intercept them or compile the library with - // instrumentation. - switch (LF) { - case LibFunc_atomic_load: - visitLibAtomicLoad(CB); - return; - case LibFunc_atomic_store: - visitLibAtomicStore(CB); - return; - default: - break; - } - } - if (auto *Call = dyn_cast(&CB)) { assert(!isa(Call) && "intrinsics are handled elsewhere"); diff --git a/llvm/test/Instrumentation/MemorySanitizer/libatomic.ll b/llvm/test/Instrumentation/MemorySanitizer/libatomic.ll deleted file mode 100644 index a2515740b4591..0000000000000 --- a/llvm/test/Instrumentation/MemorySanitizer/libatomic.ll +++ /dev/null @@ -1,70 +0,0 @@ -; RUN: opt < %s -msan-check-access-address=0 -S -passes=msan 2>&1 | FileCheck %s -; RUN: opt < %s -msan-check-access-address=0 -msan-track-origins=2 -S -passes=msan 2>&1 | FileCheck %s -check-prefixes=CHECK,CHECK-ORIGIN -; RUN: opt < %s -msan -msan-check-access-address=0 -S | FileCheck %s -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -declare void @__atomic_load(i64, i8*, i8*, i32) -declare void @__atomic_store(i64, i8*, i8*, i32) - -define i24 @odd_sized_load(i24* %ptr) sanitize_memory { -; CHECK: @odd_sized_load(i24* {{.*}}[[PTR:%.+]]) -; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1 -; CHECK-ORIGIN: @__msan_set_alloca_origin -; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8* -; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8* -; CHECK: call void @__atomic_load(i64 3, i8* [[PTR_I8]], i8* [[VAL_PTR_I8]], i32 2) - -; CHECK: ptrtoint i8* [[PTR_I8]] -; CHECK: xor -; CHECK: [[SPTR_I8:%.*]] = inttoptr -; CHECK-ORIGIN: add -; CHECK-ORIGIN: and -; CHECK-ORIGIN: [[OPTR:%.*]] = inttoptr - -; CHECK: ptrtoint i8* [[VAL_PTR_I8]] -; CHECK: xor -; CHECK: [[VAL_SPTR_I8:%.*]] = inttoptr -; CHECK-ORIGIN: add -; CHECK-ORIGIN: and -; CHECK-ORIGIN: [[VAL_OPTR:%.*]] = inttoptr - -; CHECK: call void @llvm.memcpy{{.*}}(i8* align 1 [[VAL_SPTR_I8]], i8* align 1 [[SPTR_I8]], i64 3 - -; CHECK-ORIGIN: [[ARG_ORIGIN:%.*]] = load i32, i32* [[OPTR]] -; CHECK-ORIGIN: [[VAL_ORIGIN:%.*]] = call i32 @__msan_chain_origin(i32 [[ARG_ORIGIN]]) -; CHECK-ORIGIN: call void @__msan_set_origin(i8* [[VAL_PTR_I8]], i64 3, i32 [[VAL_ORIGIN]]) - -; CHECK: [[VAL:%.*]] = load i24, i24* [[VAL_PTR]] -; CHECK: ret i24 [[VAL]] - %val_ptr = alloca i24, align 1 - %val_ptr_i8 = bitcast i24* %val_ptr to i8* - %ptr_i8 = bitcast i24* %ptr to i8* - call void @__atomic_load(i64 3, i8* %ptr_i8, i8* %val_ptr_i8, i32 0) - %val = load i24, i24* %val_ptr - ret i24 %val -} - -define void @odd_sized_store(i24* %ptr, i24 %val) sanitize_memory { -; CHECK: @odd_sized_store(i24* {{.*}}[[PTR:%.+]], i24 {{.*}}[[VAL:%.+]]) -; CHECK: [[VAL_PTR:%.*]] = alloca i24, align 1 -; CHECK: store i24 [[VAL]], i24* [[VAL_PTR]] -; CHECK: [[VAL_PTR_I8:%.*]] = bitcast i24* [[VAL_PTR]] to i8* -; CHECK: [[PTR_I8:%.*]] = bitcast i24* [[PTR]] to i8* - -; CHECK: ptrtoint i8* [[PTR_I8]] -; CHECK: xor -; CHECK: [[SPTR_I8:%.*]] = inttoptr -; CHECK: call void @llvm.memset{{.*}}(i8* align 1 [[SPTR_I8]], i8 0, i64 3 -; CHECK-ORIGIN: call void @__msan_set_origin(i8* [[PTR_I8]], i64 3, i32 0) - -; CHECK: call void @__atomic_store(i64 3, i8* [[VAL_PTR_I8]], i8* [[PTR_I8]], i32 3) -; CHECK: ret void - %val_ptr = alloca i24, align 1 - store i24 %val, i24* %val_ptr - %val_ptr_i8 = bitcast i24* %val_ptr to i8* - %ptr_i8 = bitcast i24* %ptr to i8* - call void @__atomic_store(i64 3, i8* %val_ptr_i8, i8* %ptr_i8, i32 0) - ret void -} - From 65936fed1490dd1ef8d9a0a88b7d305b0840eb05 Mon Sep 17 00:00:00 2001 From: Gui Andrade Date: Sat, 18 Jul 2020 03:49:17 +0000 Subject: [PATCH 707/771] [MSAN tests] Require android for sigandorset.cpp --- compiler-rt/test/msan/Linux/sigandorset.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler-rt/test/msan/Linux/sigandorset.cpp b/compiler-rt/test/msan/Linux/sigandorset.cpp index d0e552fcfa019..da983020a4c68 100644 --- a/compiler-rt/test/msan/Linux/sigandorset.cpp +++ b/compiler-rt/test/msan/Linux/sigandorset.cpp @@ -2,6 +2,7 @@ // RUN: %clangxx_msan -DLEFT_OK -std=c++11 -O0 -g %s -o %t && not %run %t 2>&1 | FileCheck %s // RUN: %clangxx_msan -DRIGHT_OK -std=c++11 -O0 -g %s -o %t && not %run %t 2<&1 | FileCheck %s // RUN: %clangxx_msan -DLEFT_OK -DRIGHT_OK -std=c++11 -O0 -g %s -o %t && %run %t +// REQUIRES: !android #include #include From b922004ea29d54534c4f09b9cfa655bf5f3360f0 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 17 Jul 2020 23:29:50 -0700 Subject: [PATCH 708/771] [RelocationResolver] Support R_PPC_REL32 & R_PPC64_REL{32,64} This suppresses `failed to compute relocation: R_PPC_REL32, Invalid data was encountered while parsing the file` and its 64-bit variants when running llvm-dwarfdump on a PowerPC object file with .eh_frame Unfortunately it is difficult to test the computation: DWARFDataExtractor::getEncodedPointer does not use the relocated value and even if it does, we need to teach llvm-dwarfdump --eh-frame to do some linker job to report a reasonable address. --- llvm/lib/Object/RelocationResolver.cpp | 20 +++++++++++-- llvm/test/DebugInfo/PowerPC/eh-frame.ll | 39 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 llvm/test/DebugInfo/PowerPC/eh-frame.ll diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp index 93917655073fc..77df7fd0aad9d 100644 --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -152,6 +152,8 @@ static bool supportsPPC64(uint64_t Type) { switch (Type) { case ELF::R_PPC64_ADDR32: case ELF::R_PPC64_ADDR64: + case ELF::R_PPC64_REL32: + case ELF::R_PPC64_REL64: return true; default: return false; @@ -164,6 +166,10 @@ static uint64_t resolvePPC64(RelocationRef R, uint64_t S, uint64_t A) { return (S + getELFAddend(R)) & 0xFFFFFFFF; case ELF::R_PPC64_ADDR64: return S + getELFAddend(R); + case ELF::R_PPC64_REL32: + return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF; + case ELF::R_PPC64_REL64: + return S + getELFAddend(R) - R.getOffset(); default: llvm_unreachable("Invalid relocation type"); } @@ -259,12 +265,22 @@ static uint64_t resolveX86(RelocationRef R, uint64_t S, uint64_t A) { } static bool supportsPPC32(uint64_t Type) { - return Type == ELF::R_PPC_ADDR32; + switch (Type) { + case ELF::R_PPC_ADDR32: + case ELF::R_PPC_REL32: + return true; + default: + return false; + } } static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) { - if (R.getType() == ELF::R_PPC_ADDR32) + switch (R.getType()) { + case ELF::R_PPC_ADDR32: return (S + getELFAddend(R)) & 0xFFFFFFFF; + case ELF::R_PPC_REL32: + return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF; + } llvm_unreachable("Invalid relocation type"); } diff --git a/llvm/test/DebugInfo/PowerPC/eh-frame.ll b/llvm/test/DebugInfo/PowerPC/eh-frame.ll new file mode 100644 index 0000000000000..3a8f7df6b61a9 --- /dev/null +++ b/llvm/test/DebugInfo/PowerPC/eh-frame.ll @@ -0,0 +1,39 @@ +; RUN: llc -filetype=obj -mtriple=powerpc %s -o %t32.o +; RUN: llvm-readobj -r %t32.o | FileCheck %s --check-prefix=PPC_REL +; RUN: llvm-dwarfdump --eh-frame %t32.o 2>&1 | FileCheck %s --check-prefix=PPC + +; PPC_REL: R_PPC_REL32 .text 0x0 +; PPC_REL-NEXT: R_PPC_REL32 .text 0x4 + +; PPC-NOT: warning: +; PPC: FDE cie=00000000 pc=00000000...00000004 +;; TODO Take relocation into consideration +; PPC: FDE cie=00000000 pc=00000000...00000004 + +; RUN: llc -filetype=obj -mtriple=ppc64 %s -o %t64.o +; RUN: llvm-readobj -r %t64.o | FileCheck %s --check-prefix=PPC64_REL +; RUN: llvm-dwarfdump --eh-frame %t64.o 2>&1 | FileCheck %s --check-prefix=PPC64 + +; PPC64_REL: R_PPC64_REL32 .text 0x0 +; PPC64_REL-NEXT: R_PPC64_REL32 .text 0x10 + +; PPC64-NOT: warning: +; PPC64: FDE cie=00000000 pc=00000000...00000010 +; PPC64: FDE cie=00000000 pc=00000000...00000010 + +; RUN: llc -filetype=obj -mtriple=ppc64le -code-model=large %s -o %t64l.o +; RUN: llvm-readobj -r %t64l.o | FileCheck %s --check-prefix=PPC64L_REL +; RUN: llvm-dwarfdump --eh-frame %t64l.o 2>&1 | FileCheck %s --check-prefix=PPC64 + +; PPC64L_REL: R_PPC64_REL64 .text 0x0 +; PPC64L_REL-NEXT: R_PPC64_REL64 .text 0x10 + +define void @foo() { +entry: + ret void +} + +define void @bar() { +entry: + ret void +} From 3073a3aa1ef1ce8c9cac9b97a8e5905dd8779e16 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Fri, 17 Jul 2020 23:49:15 -0700 Subject: [PATCH 709/771] [RelocationResolver] Support R_AARCH64_PREL32 Code from D83800 by Yichao Yu --- llvm/lib/Object/RelocationResolver.cpp | 6 ++++++ llvm/test/DebugInfo/AArch64/eh-frame.ll | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 llvm/test/DebugInfo/AArch64/eh-frame.ll diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp index 77df7fd0aad9d..919799a25c6f2 100644 --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -62,6 +62,8 @@ static bool supportsAArch64(uint64_t Type) { switch (Type) { case ELF::R_AARCH64_ABS32: case ELF::R_AARCH64_ABS64: + case ELF::R_AARCH64_PREL32: + case ELF::R_AARCH64_PREL64: return true; default: return false; @@ -74,6 +76,10 @@ static uint64_t resolveAArch64(RelocationRef R, uint64_t S, uint64_t A) { return (S + getELFAddend(R)) & 0xFFFFFFFF; case ELF::R_AARCH64_ABS64: return S + getELFAddend(R); + case ELF::R_AARCH64_PREL32: + return (S + getELFAddend(R) - R.getOffset()) & 0xFFFFFFFF; + case ELF::R_AARCH64_PREL64: + return S + getELFAddend(R) - R.getOffset(); default: llvm_unreachable("Invalid relocation type"); } diff --git a/llvm/test/DebugInfo/AArch64/eh-frame.ll b/llvm/test/DebugInfo/AArch64/eh-frame.ll new file mode 100644 index 0000000000000..9651159271e55 --- /dev/null +++ b/llvm/test/DebugInfo/AArch64/eh-frame.ll @@ -0,0 +1,21 @@ +; RUN: llc -filetype=obj -mtriple=aarch64 %s -o %t.o +; RUN: llvm-readobj -r %t.o | FileCheck %s --check-prefix=REL32 +; RUN: llvm-dwarfdump --eh-frame %t.o 2>&1 | FileCheck %s + +; REL32: R_AARCH64_PREL32 .text 0x0 +; REL32-NEXT: R_AARCH64_PREL32 .text 0x4 + +; CHECK-NOT: warning: +; CHECK: FDE cie=00000000 pc=00000000...00000004 +;; TODO Take relocation into consideration +; CHECK: FDE cie=00000000 pc=00000000...00000004 + +define void @foo() { +entry: + ret void +} + +define void @bar() { +entry: + ret void +} From 3382b7177f0410144d70154aee9b2031221ba838 Mon Sep 17 00:00:00 2001 From: Yash Jain Date: Sat, 18 Jul 2020 13:09:30 +0530 Subject: [PATCH 710/771] [MLIR] Add lowering for affine.parallel to scf.parallel Add lowering conversion from affine.parallel to scf.parallel. Differential Revision: https://reviews.llvm.org/D83239 --- .../AffineToStandard/AffineToStandard.h | 1 + .../AffineToStandard/AffineToStandard.cpp | 38 +++++++++++++ .../AffineToStandard/lower-affine.mlir | 54 +++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/mlir/include/mlir/Conversion/AffineToStandard/AffineToStandard.h b/mlir/include/mlir/Conversion/AffineToStandard/AffineToStandard.h index 5d04f157b8ce8..4deffafe0ec60 100644 --- a/mlir/include/mlir/Conversion/AffineToStandard/AffineToStandard.h +++ b/mlir/include/mlir/Conversion/AffineToStandard/AffineToStandard.h @@ -15,6 +15,7 @@ namespace mlir { class AffineExpr; class AffineForOp; class AffineMap; +class AffineParallelOp; class Location; struct LogicalResult; class MLIRContext; diff --git a/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp b/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp index e8032348e1821..bc48ef35fcd10 100644 --- a/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp +++ b/mlir/lib/Conversion/AffineToStandard/AffineToStandard.cpp @@ -357,6 +357,43 @@ class AffineForLowering : public OpRewritePattern { } }; +/// Convert an `affine.parallel` (loop nest) operation into a `scf.parallel` +/// operation. +class AffineParallelLowering : public OpRewritePattern { +public: + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(AffineParallelOp op, + PatternRewriter &rewriter) const override { + Location loc = op.getLoc(); + SmallVector steps; + SmallVector upperBoundTuple; + SmallVector lowerBoundTuple; + // Finding lower and upper bound by expanding the map expression. + // Checking if expandAffineMap is not giving NULL. + Optional> upperBound = expandAffineMap( + rewriter, loc, op.upperBoundsMap(), op.getUpperBoundsOperands()); + Optional> lowerBound = expandAffineMap( + rewriter, loc, op.lowerBoundsMap(), op.getLowerBoundsOperands()); + if (!lowerBound || !upperBound) + return failure(); + upperBoundTuple = *upperBound; + lowerBoundTuple = *lowerBound; + steps.reserve(op.steps().size()); + for (Attribute step : op.steps()) + steps.push_back(rewriter.create( + loc, step.cast().getInt())); + // Creating empty scf.parallel op body with appropriate bounds. + auto parallelOp = rewriter.create(loc, lowerBoundTuple, + upperBoundTuple, steps); + rewriter.eraseBlock(parallelOp.getBody()); + rewriter.inlineRegionBefore(op.region(), parallelOp.region(), + parallelOp.region().end()); + rewriter.eraseOp(op); + return success(); + } +}; + class AffineIfLowering : public OpRewritePattern { public: using OpRewritePattern::OpRewritePattern; @@ -615,6 +652,7 @@ void mlir::populateAffineToStdConversionPatterns( AffineLoadLowering, AffineMinLowering, AffineMaxLowering, + AffineParallelLowering, AffinePrefetchLowering, AffineStoreLowering, AffineForLowering, diff --git a/mlir/test/Conversion/AffineToStandard/lower-affine.mlir b/mlir/test/Conversion/AffineToStandard/lower-affine.mlir index 2ca3ffe947fbd..7aac76b870b74 100644 --- a/mlir/test/Conversion/AffineToStandard/lower-affine.mlir +++ b/mlir/test/Conversion/AffineToStandard/lower-affine.mlir @@ -620,3 +620,57 @@ func @affine_max(%arg0: index, %arg1: index) -> index{ %0 = affine.max affine_map<(d0,d1) -> (d0 - d1, d1 - d0)>(%arg0, %arg1) return %0 : index } + +// CHECK-LABEL: func @affine_parallel( +// CHECK-SAME: %[[ARG0:.*]]: memref<100x100xf32>, %[[ARG1:.*]]: memref<100x100xf32>) { +func @affine_parallel(%o: memref<100x100xf32>, %a: memref<100x100xf32>) { + affine.parallel (%i, %j) = (0, 0) to (100, 100) { + } + return +} + +// CHECK-DAG: %[[C100:.*]] = constant 100 +// CHECK-DAG: %[[C100_1:.*]] = constant 100 +// CHECK-DAG: %[[C0:.*]] = constant 0 +// CHECK-DAG: %[[C0_1:.*]] = constant 0 +// CHECK-DAG: %[[C1:.*]] = constant 1 +// CHECK-DAG: %[[C1_1:.*]] = constant 1 +// CHECK-DAG: scf.parallel (%arg2, %arg3) = (%[[C0]], %[[C0_1]]) to (%[[C100]], %[[C100_1]]) step (%[[C1]], %[[C1_1]]) { + +// CHECK-LABEL: func @affine_parallel_tiled( +// CHECK-SAME: %[[ARG0:.*]]: memref<100x100xf32>, %[[ARG1:.*]]: memref<100x100xf32>, %[[ARG2:.*]]: memref<100x100xf32>) { +func @affine_parallel_tiled(%o: memref<100x100xf32>, %a: memref<100x100xf32>, %b: memref<100x100xf32>) { + affine.parallel (%i0, %j0, %k0) = (0, 0, 0) to (100, 100, 100) step (10, 10, 10) { + affine.parallel (%i1, %j1, %k1) = (%i0, %j0, %k0) to (%i0 + 10, %j0 + 10, %k0 + 10) { + %0 = affine.load %a[%i1, %k1] : memref<100x100xf32> + %1 = affine.load %b[%k1, %j1] : memref<100x100xf32> + %2 = mulf %0, %1 : f32 + } + } + return +} + +// CHECK-DAG: %[[C100:.*]] = constant 100 +// CHECK-DAG: %[[C100_0:.*]] = constant 100 +// CHECK-DAG: %[[C100_1:.*]] = constant 100 +// CHECK-DAG: %[[C0:.*]] = constant 0 +// CHECK-DAG: %[[C0_2:.*]] = constant 0 +// CHECK-DAG: %[[C0_3:.*]] = constant 0 +// CHECK-DAG: %[[C10:.*]] = constant 10 +// CHECK-DAG: %[[C10_4:.*]] = constant 10 +// CHECK-DAG: %[[C10_5:.*]] = constant 10 +// CHECK: scf.parallel (%[[arg3:.*]], %[[arg4:.*]], %[[arg5:.*]]) = (%[[C0]], %[[C0_2]], %[[C0_3]]) to (%[[C100]], %[[C100_0]], %[[C100_1]]) step (%[[C10]], %[[C10_4]], %[[C10_5]]) { +// CHECK-DAG: %[[C10_6:.*]] = constant 10 +// CHECK-DAG: %[[A0:.*]] = addi %[[arg3]], %[[C10_6]] +// CHECK-DAG: %[[C10_7:.*]] = constant 10 +// CHECK-DAG: %[[A1:.*]] = addi %[[arg4]], %[[C10_7]] +// CHECK-DAG: %[[C10_8:.*]] = constant 10 +// CHECK-DAG: %[[A2:.*]] = addi %[[arg5]], %[[C10_8]] +// CHECK-DAG: %[[C1:.*]] = constant 1 +// CHECK-DAG: %[[C1_9:.*]] = constant 1 +// CHECK-DAG: %[[C1_10:.*]] = constant 1 +// CHECK: scf.parallel (%[[arg6:.*]], %[[arg7:.*]], %[[arg8:.*]]) = (%[[arg3]], %[[arg4]], %[[arg5]]) to (%[[A0]], %[[A1]], %[[A2]]) step (%[[C1]], %[[C1_9]], %[[C1_10]]) { +// CHECK: %[[A3:.*]] = load %[[ARG1]][%[[arg6]], %[[arg8]]] : memref<100x100xf32> +// CHECK: %[[A4:.*]] = load %[[ARG2]][%[[arg8]], %[[arg7]]] : memref<100x100xf32> +// CHECK: mulf %[[A3]], %[[A4]] : f32 +// CHECK: scf.yield From 1fe0705cb17ab48aab0e486db1148e00e544c0d3 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Sat, 18 Jul 2020 02:16:17 -0700 Subject: [PATCH 711/771] [sanitizer] Disable test on incompatible platforms --- .../test/sanitizer_common/TestCases/Linux/signal_send.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_send.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_send.cpp index 54014da8b532a..84084b9291a70 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_send.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/signal_send.cpp @@ -1,5 +1,8 @@ // RUN: %clangxx -std=c++11 -O0 -g %s -o %t && %run %t 2>&1 | FileCheck %s +// sigandset is glibc specific. +// UNSUPPORTED: android, freebsd, netbsd + #include #include #include From 24089928be7cb04a40975f4d037b1a1c15034614 Mon Sep 17 00:00:00 2001 From: Evgeny Leviant Date: Sat, 18 Jul 2020 14:11:40 +0300 Subject: [PATCH 712/771] [CodeGen][TargetPassConfig] Add TargetTransformInfo pass correctly Patch adds tti pass directly enforcing its execution with correctly set TargetTransformInfo. Differential revision: https://reviews.llvm.org/D84047 --- llvm/lib/CodeGen/TargetPassConfig.cpp | 2 +- .../AArch64/partial-pipeline-execution.ll | 87 +++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AArch64/partial-pipeline-execution.ll diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index e0fdb0cefcb8b..ffff56f545b2d 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -879,7 +879,7 @@ bool TargetPassConfig::addISelPasses() { addPass(createLowerEmuTLSPass()); addPass(createPreISelIntrinsicLoweringPass()); - addPass(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); + PM->add(createTargetTransformInfoWrapperPass(TM->getTargetIRAnalysis())); addIRPasses(); addCodeGenPrepare(); addPassesToHandleExceptions(); diff --git a/llvm/test/CodeGen/AArch64/partial-pipeline-execution.ll b/llvm/test/CodeGen/AArch64/partial-pipeline-execution.ll new file mode 100644 index 0000000000000..82cb0a35f2a58 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/partial-pipeline-execution.ll @@ -0,0 +1,87 @@ +; RUN: llc -O3 %s -o %t.s +; RUN: llc -O3 -stop-after=atomic-expand %s -o %t.mir +; RUN: llc -O3 -start-after=atomic-expand %s -o %t2.s + +; If we add tti pass correctly files should be identical +; Otherwise LSR will use default TargetTransformInfo and +; optimize the loop differently +; RUN: cmp %t.s %t2.s + +; ModuleID = 'loop.c' +source_filename = "loop.c" +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" +target triple = "aarch64-none-linux-gnu" + +@q = dso_local local_unnamed_addr global i32* null, align 8 + +; Function Attrs: nofree norecurse nounwind +define dso_local i32 @main(i32 %argc, i8** nocapture readnone %argv) local_unnamed_addr #0 { +entry: + %cmp5 = icmp sgt i32 %argc, 0 + br i1 %cmp5, label %for.body.lr.ph, label %for.cond.cleanup + +for.body.lr.ph: ; preds = %entry + %0 = load i32*, i32** @q, align 8, !tbaa !2 + %1 = zext i32 %argc to i64 + %2 = add nsw i64 %1, -1 + %3 = lshr i64 %2, 5 + %4 = add nuw nsw i64 %3, 1 + %min.iters.check = icmp eq i64 %3, 0 + br i1 %min.iters.check, label %for.body.preheader, label %vector.ph + +for.body.preheader: ; preds = %middle.block, %for.body.lr.ph + %indvars.iv.ph = phi i64 [ 0, %for.body.lr.ph ], [ %ind.end, %middle.block ] + br label %for.body + +vector.ph: ; preds = %for.body.lr.ph + %n.vec = and i64 %4, 1152921504606846974 + %ind.end = shl i64 %n.vec, 5 + br label %vector.body + +vector.body: ; preds = %vector.body, %vector.ph + %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ] + %offset.idx = shl i64 %index, 5 + %induction7 = or i64 %offset.idx, 32 + %5 = getelementptr inbounds i32, i32* %0, i64 %offset.idx + %6 = getelementptr inbounds i32, i32* %0, i64 %induction7 + %7 = trunc i64 %offset.idx to i32 + %8 = trunc i64 %induction7 to i32 + store i32 %7, i32* %5, align 4, !tbaa !6 + store i32 %8, i32* %6, align 4, !tbaa !6 + %index.next = add i64 %index, 2 + %9 = icmp eq i64 %index.next, %n.vec + br i1 %9, label %middle.block, label %vector.body, !llvm.loop !8 + +middle.block: ; preds = %vector.body + %cmp.n = icmp eq i64 %4, %n.vec + br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader + +for.cond.cleanup: ; preds = %for.body, %middle.block, %entry + ret i32 0 + +for.body: ; preds = %for.body.preheader, %for.body + %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ %indvars.iv.ph, %for.body.preheader ] + %arrayidx = getelementptr inbounds i32, i32* %0, i64 %indvars.iv + %10 = trunc i64 %indvars.iv to i32 + store i32 %10, i32* %arrayidx, align 4, !tbaa !6 + %indvars.iv.next = add nuw nsw i64 %indvars.iv, 32 + %cmp = icmp ult i64 %indvars.iv.next, %1 + br i1 %cmp, label %for.body, label %for.cond.cleanup, !llvm.loop !10 +} + +attributes #0 = { nofree norecurse nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="non-leaf" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "target-features"="+neon" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 11.0.0 (https://github.com/llvm/llvm-project.git d9943e7f0ce888733ee7ba91da432e5f01f7aa85)"} +!2 = !{!3, !3, i64 0} +!3 = !{!"any pointer", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C/C++ TBAA"} +!6 = !{!7, !7, i64 0} +!7 = !{!"int", !4, i64 0} +!8 = distinct !{!8, !9} +!9 = !{!"llvm.loop.isvectorized", i32 1} +!10 = distinct !{!10, !9} From 2f4c3e80970c85078747a528b0af0fc5168e3e1a Mon Sep 17 00:00:00 2001 From: David Green Date: Fri, 17 Jul 2020 08:35:04 +0100 Subject: [PATCH 713/771] [LV] Add additional InLoop redution tests. NFC --- .../LoopVectorize/ARM/mve-reductions.ll | 1290 ++++++++++++++ .../LoopVectorize/reduction-inloop-uf4.ll | 68 + .../LoopVectorize/reduction-inloop.ll | 1493 +++++++---------- 3 files changed, 1970 insertions(+), 881 deletions(-) create mode 100644 llvm/test/Transforms/LoopVectorize/ARM/mve-reductions.ll create mode 100644 llvm/test/Transforms/LoopVectorize/reduction-inloop-uf4.ll diff --git a/llvm/test/Transforms/LoopVectorize/ARM/mve-reductions.ll b/llvm/test/Transforms/LoopVectorize/ARM/mve-reductions.ll new file mode 100644 index 0000000000000..0d4cc31677b80 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/ARM/mve-reductions.ll @@ -0,0 +1,1290 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -loop-vectorize < %s -S -o - | FileCheck %s + +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" +target triple = "thumbv8.1m.main-arm-none-eabi" + +define i64 @add_i64_i64(i64* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i64_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[R_07:%.*]] = phi i64 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[X:%.*]], i32 [[I_08]] +; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[ARRAYIDX]], align 8 +; CHECK-NEXT: [[ADD]] = add nsw i64 [[TMP0]], [[R_07]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[FOR_BODY]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i64 [[R_0_LCSSA]] +; +entry: + %cmp6 = icmp sgt i32 %n, 0 + br i1 %cmp6, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.07 = phi i64 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i64, i64* %x, i32 %i.08 + %0 = load i64, i64* %arrayidx, align 8 + %add = add nsw i64 %0, %r.07 + %inc = add nuw nsw i32 %i.08, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] + ret i64 %r.0.lcssa +} + +; FIXME: 4x +define i64 @add_i32_i64(i32* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i32_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[R_07:%.*]] = phi i64 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[X:%.*]], i32 [[I_08]] +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 +; CHECK-NEXT: [[ADD]] = add nsw i64 [[R_07]], [[CONV]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[FOR_BODY]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i64 [[R_0_LCSSA]] +; +entry: + %cmp6 = icmp sgt i32 %n, 0 + br i1 %cmp6, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.07 = phi i64 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i32, i32* %x, i32 %i.08 + %0 = load i32, i32* %arrayidx, align 4 + %conv = sext i32 %0 to i64 + %add = add nsw i64 %r.07, %conv + %inc = add nuw nsw i32 %i.08, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] + ret i64 %r.0.lcssa +} + +; FIXME: 4x ? +define i64 @add_i16_i64(i16* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i16_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[R_07:%.*]] = phi i64 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i16, i16* [[X:%.*]], i32 [[I_08]] +; CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[ARRAYIDX]], align 2 +; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i64 +; CHECK-NEXT: [[ADD]] = add nsw i64 [[R_07]], [[CONV]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[FOR_BODY]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i64 [[R_0_LCSSA]] +; +entry: + %cmp6 = icmp sgt i32 %n, 0 + br i1 %cmp6, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.07 = phi i64 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i16, i16* %x, i32 %i.08 + %0 = load i16, i16* %arrayidx, align 2 + %conv = sext i16 %0 to i64 + %add = add nsw i64 %r.07, %conv + %inc = add nuw nsw i32 %i.08, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] + ret i64 %r.0.lcssa +} + +; FIXME: 4x ? +define i64 @add_i8_i64(i8* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i8_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[R_07:%.*]] = phi i64 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i32 [[I_08]] +; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP0]] to i64 +; CHECK-NEXT: [[ADD]] = add nuw nsw i64 [[R_07]], [[CONV]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[FOR_BODY]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i64 [[R_0_LCSSA]] +; +entry: + %cmp6 = icmp sgt i32 %n, 0 + br i1 %cmp6, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.07 = phi i64 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i8, i8* %x, i32 %i.08 + %0 = load i8, i8* %arrayidx, align 1 + %conv = zext i8 %0 to i64 + %add = add nuw nsw i64 %r.07, %conv + %inc = add nuw nsw i32 %i.08, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] + ret i64 %r.0.lcssa +} + +define i32 @add_i32_i32(i32* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i32_i32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4]] = add <4 x i32> [[WIDE_LOAD]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP4]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_07:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 [[I_08]] +; CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[ADD]] = add nsw i32 [[TMP7]], [[R_07]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !2 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i32 [[R_0_LCSSA]] +; +entry: + %cmp6 = icmp sgt i32 %n, 0 + br i1 %cmp6, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.07 = phi i32 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i32, i32* %x, i32 %i.08 + %0 = load i32, i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.07 + %inc = add nuw nsw i32 %i.08, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ] + ret i32 %r.0.lcssa +} + +; FIXME: 8x +define i32 @add_i16_i32(i16* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i16_i32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, i16* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, i16* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16* [[TMP2]] to <4 x i16>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, <4 x i16>* [[TMP3]], align 2 +; CHECK-NEXT: [[TMP4:%.*]] = sext <4 x i16> [[WIDE_LOAD]] to <4 x i32> +; CHECK-NEXT: [[TMP5]] = add <4 x i32> [[VEC_PHI]], [[TMP4]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !4 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_07:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i16, i16* [[X]], i32 [[I_08]] +; CHECK-NEXT: [[TMP8:%.*]] = load i16, i16* [[ARRAYIDX]], align 2 +; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[TMP8]] to i32 +; CHECK-NEXT: [[ADD]] = add nsw i32 [[R_07]], [[CONV]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !5 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i32 [[R_0_LCSSA]] +; +entry: + %cmp6 = icmp sgt i32 %n, 0 + br i1 %cmp6, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.07 = phi i32 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i16, i16* %x, i32 %i.08 + %0 = load i16, i16* %arrayidx, align 2 + %conv = sext i16 %0 to i32 + %add = add nsw i32 %r.07, %conv + %inc = add nuw nsw i32 %i.08, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ] + ret i32 %r.0.lcssa +} + +; FIXME: 16x +define i32 @add_i8_i32(i8* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i8_i32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to <4 x i8>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP3]], align 1 +; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[WIDE_LOAD]] to <4 x i32> +; CHECK-NEXT: [[TMP5]] = add <4 x i32> [[VEC_PHI]], [[TMP4]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !6 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_07:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X]], i32 [[I_08]] +; CHECK-NEXT: [[TMP8:%.*]] = load i8, i8* [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP8]] to i32 +; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[R_07]], [[CONV]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_08]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !7 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i32 [[R_0_LCSSA]] +; +entry: + %cmp6 = icmp sgt i32 %n, 0 + br i1 %cmp6, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.08 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.07 = phi i32 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i8, i8* %x, i32 %i.08 + %0 = load i8, i8* %arrayidx, align 1 + %conv = zext i8 %0 to i32 + %add = add nuw nsw i32 %r.07, %conv + %inc = add nuw nsw i32 %i.08, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ] + ret i32 %r.0.lcssa +} + +define signext i16 @add_i16_i16(i16* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i16_i16( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP8:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP8]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 8 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i16> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, i16* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, i16* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16* [[TMP2]] to <8 x i16>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, <8 x i16>* [[TMP3]], align 2 +; CHECK-NEXT: [[TMP4]] = add <8 x i16> [[WIDE_LOAD]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !8 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP6:%.*]] = call i16 @llvm.experimental.vector.reduce.add.v8i16(<8 x i16> [[TMP4]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i16 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_010:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_09:%.*]] = phi i16 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i16, i16* [[X]], i32 [[I_010]] +; CHECK-NEXT: [[TMP7:%.*]] = load i16, i16* [[ARRAYIDX]], align 2 +; CHECK-NEXT: [[ADD]] = add i16 [[TMP7]], [[R_09]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_010]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !9 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i16 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i16 [[R_0_LCSSA]] +; +entry: + %cmp8 = icmp sgt i32 %n, 0 + br i1 %cmp8, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.010 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.09 = phi i16 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i16, i16* %x, i32 %i.010 + %0 = load i16, i16* %arrayidx, align 2 + %add = add i16 %0, %r.09 + %inc = add nuw nsw i32 %i.010, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ] + ret i16 %r.0.lcssa +} + +; FIXME: 16x ? +define signext i16 @add_i8_i16(i8* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i8_i16( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP8:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP8]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 8 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i16> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to <8 x i8>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[TMP3]], align 1 +; CHECK-NEXT: [[TMP4:%.*]] = zext <8 x i8> [[WIDE_LOAD]] to <8 x i16> +; CHECK-NEXT: [[TMP5]] = add <8 x i16> [[VEC_PHI]], [[TMP4]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !10 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP7:%.*]] = call i16 @llvm.experimental.vector.reduce.add.v8i16(<8 x i16> [[TMP5]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i16 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_010:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_09:%.*]] = phi i16 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X]], i32 [[I_010]] +; CHECK-NEXT: [[TMP8:%.*]] = load i8, i8* [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP8]] to i16 +; CHECK-NEXT: [[ADD]] = add i16 [[R_09]], [[CONV]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_010]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !11 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i16 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i16 [[R_0_LCSSA]] +; +entry: + %cmp8 = icmp sgt i32 %n, 0 + br i1 %cmp8, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.010 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.09 = phi i16 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i8, i8* %x, i32 %i.010 + %0 = load i8, i8* %arrayidx, align 1 + %conv = zext i8 %0 to i16 + %add = add i16 %r.09, %conv + %inc = add nuw nsw i32 %i.010, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ] + ret i16 %r.0.lcssa +} + +define zeroext i8 @add_i8_i8(i8* nocapture readonly %x, i32 %n) #0 { +; CHECK-LABEL: @add_i8_i8( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 16 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 16 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <16 x i8> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to <16 x i8>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <16 x i8>, <16 x i8>* [[TMP3]], align 1 +; CHECK-NEXT: [[TMP4]] = add <16 x i8> [[WIDE_LOAD]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 16 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !12 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP6:%.*]] = call i8 @llvm.experimental.vector.reduce.add.v16i8(<16 x i8> [[TMP4]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i8 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_09:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_08:%.*]] = phi i8 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X]], i32 [[I_09]] +; CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[ADD]] = add i8 [[TMP7]], [[R_08]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_09]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !13 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i8 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i8 [[R_0_LCSSA]] +; +entry: + %cmp7 = icmp sgt i32 %n, 0 + br i1 %cmp7, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.09 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.08 = phi i8 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i8, i8* %x, i32 %i.09 + %0 = load i8, i8* %arrayidx, align 1 + %add = add i8 %0, %r.08 + %inc = add nuw nsw i32 %i.09, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i8 [ 0, %entry ], [ %add, %for.body ] + ret i8 %r.0.lcssa +} + +define i64 @mla_i64_i64(i64* nocapture readonly %x, i64* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i64_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP8:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP8]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_010:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[R_09:%.*]] = phi i64 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i64, i64* [[X:%.*]], i32 [[I_010]] +; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[ARRAYIDX]], align 8 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i64, i64* [[Y:%.*]], i32 [[I_010]] +; CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[ARRAYIDX1]], align 8 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[TMP1]], [[TMP0]] +; CHECK-NEXT: [[ADD]] = add nsw i64 [[MUL]], [[R_09]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_010]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[FOR_BODY]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i64 [[R_0_LCSSA]] +; +entry: + %cmp8 = icmp sgt i32 %n, 0 + br i1 %cmp8, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.010 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.09 = phi i64 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i64, i64* %x, i32 %i.010 + %0 = load i64, i64* %arrayidx, align 8 + %arrayidx1 = getelementptr inbounds i64, i64* %y, i32 %i.010 + %1 = load i64, i64* %arrayidx1, align 8 + %mul = mul nsw i64 %1, %0 + %add = add nsw i64 %mul, %r.09 + %inc = add nuw nsw i32 %i.010, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] + ret i64 %r.0.lcssa +} + +define i64 @mla_i32_i64(i32* nocapture readonly %x, i32* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i32_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP8:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP8]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_010:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[R_09:%.*]] = phi i64 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[X:%.*]], i32 [[I_010]] +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[Y:%.*]], i32 [[I_010]] +; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX1]], align 4 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP1]], [[TMP0]] +; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[MUL]] to i64 +; CHECK-NEXT: [[ADD]] = add nsw i64 [[R_09]], [[CONV]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_010]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[FOR_BODY]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i64 [[R_0_LCSSA]] +; +entry: + %cmp8 = icmp sgt i32 %n, 0 + br i1 %cmp8, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.010 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.09 = phi i64 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i32, i32* %x, i32 %i.010 + %0 = load i32, i32* %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds i32, i32* %y, i32 %i.010 + %1 = load i32, i32* %arrayidx1, align 4 + %mul = mul nsw i32 %1, %0 + %conv = sext i32 %mul to i64 + %add = add nsw i64 %r.09, %conv + %inc = add nuw nsw i32 %i.010, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] + ret i64 %r.0.lcssa +} + +define i64 @mla_i16_i64(i16* nocapture readonly %x, i16* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i16_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP10:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP10]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_012:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[R_011:%.*]] = phi i64 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i16, i16* [[X:%.*]], i32 [[I_012]] +; CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* [[ARRAYIDX]], align 2 +; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[TMP0]] to i32 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, i16* [[Y:%.*]], i32 [[I_012]] +; CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* [[ARRAYIDX1]], align 2 +; CHECK-NEXT: [[CONV2:%.*]] = sext i16 [[TMP1]] to i32 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV2]], [[CONV]] +; CHECK-NEXT: [[CONV3:%.*]] = sext i32 [[MUL]] to i64 +; CHECK-NEXT: [[ADD]] = add nsw i64 [[R_011]], [[CONV3]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_012]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[FOR_BODY]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i64 [[R_0_LCSSA]] +; +entry: + %cmp10 = icmp sgt i32 %n, 0 + br i1 %cmp10, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.012 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.011 = phi i64 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i16, i16* %x, i32 %i.012 + %0 = load i16, i16* %arrayidx, align 2 + %conv = sext i16 %0 to i32 + %arrayidx1 = getelementptr inbounds i16, i16* %y, i32 %i.012 + %1 = load i16, i16* %arrayidx1, align 2 + %conv2 = sext i16 %1 to i32 + %mul = mul nsw i32 %conv2, %conv + %conv3 = sext i32 %mul to i64 + %add = add nsw i64 %r.011, %conv3 + %inc = add nuw nsw i32 %i.012, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] + ret i64 %r.0.lcssa +} + +define i64 @mla_i8_i64(i8* nocapture readonly %x, i8* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i8_i64( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP10:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP10]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_012:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[R_011:%.*]] = phi i64 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i32 [[I_012]] +; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP0]] to i32 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[Y:%.*]], i32 [[I_012]] +; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[ARRAYIDX1]], align 1 +; CHECK-NEXT: [[CONV2:%.*]] = zext i8 [[TMP1]] to i32 +; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV2]], [[CONV]] +; CHECK-NEXT: [[CONV3:%.*]] = zext i32 [[MUL]] to i64 +; CHECK-NEXT: [[ADD]] = add nuw nsw i64 [[R_011]], [[CONV3]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_012]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i64 [ [[ADD]], [[FOR_BODY]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i64 [[R_0_LCSSA]] +; +entry: + %cmp10 = icmp sgt i32 %n, 0 + br i1 %cmp10, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.012 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.011 = phi i64 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i8, i8* %x, i32 %i.012 + %0 = load i8, i8* %arrayidx, align 1 + %conv = zext i8 %0 to i32 + %arrayidx1 = getelementptr inbounds i8, i8* %y, i32 %i.012 + %1 = load i8, i8* %arrayidx1, align 1 + %conv2 = zext i8 %1 to i32 + %mul = mul nuw nsw i32 %conv2, %conv + %conv3 = zext i32 %mul to i64 + %add = add nuw nsw i64 %r.011, %conv3 + %inc = add nuw nsw i32 %i.012, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i64 [ 0, %entry ], [ %add, %for.body ] + ret i64 %r.0.lcssa +} + +define i32 @mla_i32_i32(i32* nocapture readonly %x, i32* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i32_i32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP8:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP8]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, i32* [[Y:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 +; CHECK-NEXT: [[TMP7:%.*]] = mul nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP8]] = add <4 x i32> [[TMP7]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !14 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP10:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP8]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_010:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_09:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 [[I_010]] +; CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[Y]], i32 [[I_010]] +; CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[ARRAYIDX1]], align 4 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP12]], [[TMP11]] +; CHECK-NEXT: [[ADD]] = add nsw i32 [[MUL]], [[R_09]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_010]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !15 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i32 [[R_0_LCSSA]] +; +entry: + %cmp8 = icmp sgt i32 %n, 0 + br i1 %cmp8, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.010 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.09 = phi i32 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i32, i32* %x, i32 %i.010 + %0 = load i32, i32* %arrayidx, align 4 + %arrayidx1 = getelementptr inbounds i32, i32* %y, i32 %i.010 + %1 = load i32, i32* %arrayidx1, align 4 + %mul = mul nsw i32 %1, %0 + %add = add nsw i32 %mul, %r.09 + %inc = add nuw nsw i32 %i.010, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ] + ret i32 %r.0.lcssa +} + +define i32 @mla_i16_i32(i16* nocapture readonly %x, i16* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i16_i32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP9:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP9]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP10:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, i16* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, i16* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16* [[TMP2]] to <4 x i16>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i16>, <4 x i16>* [[TMP3]], align 2 +; CHECK-NEXT: [[TMP4:%.*]] = sext <4 x i16> [[WIDE_LOAD]] to <4 x i32> +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, i16* [[Y:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i16, i16* [[TMP5]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = bitcast i16* [[TMP6]] to <4 x i16>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i16>, <4 x i16>* [[TMP7]], align 2 +; CHECK-NEXT: [[TMP8:%.*]] = sext <4 x i16> [[WIDE_LOAD1]] to <4 x i32> +; CHECK-NEXT: [[TMP9:%.*]] = mul nsw <4 x i32> [[TMP8]], [[TMP4]] +; CHECK-NEXT: [[TMP10]] = add <4 x i32> [[TMP9]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP11]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !16 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP12:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP10]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP12]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_011:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_010:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i16, i16* [[X]], i32 [[I_011]] +; CHECK-NEXT: [[TMP13:%.*]] = load i16, i16* [[ARRAYIDX]], align 2 +; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[TMP13]] to i32 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, i16* [[Y]], i32 [[I_011]] +; CHECK-NEXT: [[TMP14:%.*]] = load i16, i16* [[ARRAYIDX1]], align 2 +; CHECK-NEXT: [[CONV2:%.*]] = sext i16 [[TMP14]] to i32 +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[CONV2]], [[CONV]] +; CHECK-NEXT: [[ADD]] = add nsw i32 [[MUL]], [[R_010]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_011]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !17 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP12]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i32 [[R_0_LCSSA]] +; +entry: + %cmp9 = icmp sgt i32 %n, 0 + br i1 %cmp9, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.011 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.010 = phi i32 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i16, i16* %x, i32 %i.011 + %0 = load i16, i16* %arrayidx, align 2 + %conv = sext i16 %0 to i32 + %arrayidx1 = getelementptr inbounds i16, i16* %y, i32 %i.011 + %1 = load i16, i16* %arrayidx1, align 2 + %conv2 = sext i16 %1 to i32 + %mul = mul nsw i32 %conv2, %conv + %add = add nsw i32 %mul, %r.010 + %inc = add nuw nsw i32 %i.011, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ] + ret i32 %r.0.lcssa +} + +define i32 @mla_i8_i32(i8* nocapture readonly %x, i8* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i8_i32( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP9:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP9]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 4 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP10:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to <4 x i8>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP3]], align 1 +; CHECK-NEXT: [[TMP4:%.*]] = zext <4 x i8> [[WIDE_LOAD]] to <4 x i32> +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, i8* [[Y:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, i8* [[TMP5]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = bitcast i8* [[TMP6]] to <4 x i8>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i8>, <4 x i8>* [[TMP7]], align 1 +; CHECK-NEXT: [[TMP8:%.*]] = zext <4 x i8> [[WIDE_LOAD1]] to <4 x i32> +; CHECK-NEXT: [[TMP9:%.*]] = mul nuw nsw <4 x i32> [[TMP8]], [[TMP4]] +; CHECK-NEXT: [[TMP10]] = add <4 x i32> [[TMP9]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP11]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !18 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP12:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP10]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP12]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_011:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_010:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X]], i32 [[I_011]] +; CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP13]] to i32 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[Y]], i32 [[I_011]] +; CHECK-NEXT: [[TMP14:%.*]] = load i8, i8* [[ARRAYIDX1]], align 1 +; CHECK-NEXT: [[CONV2:%.*]] = zext i8 [[TMP14]] to i32 +; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[CONV2]], [[CONV]] +; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[MUL]], [[R_010]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_011]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !19 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP12]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i32 [[R_0_LCSSA]] +; +entry: + %cmp9 = icmp sgt i32 %n, 0 + br i1 %cmp9, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.011 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.010 = phi i32 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i8, i8* %x, i32 %i.011 + %0 = load i8, i8* %arrayidx, align 1 + %conv = zext i8 %0 to i32 + %arrayidx1 = getelementptr inbounds i8, i8* %y, i32 %i.011 + %1 = load i8, i8* %arrayidx1, align 1 + %conv2 = zext i8 %1 to i32 + %mul = mul nuw nsw i32 %conv2, %conv + %add = add nuw nsw i32 %mul, %r.010 + %inc = add nuw nsw i32 %i.011, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i32 [ 0, %entry ], [ %add, %for.body ] + ret i32 %r.0.lcssa +} + +define signext i16 @mla_i16_i16(i16* nocapture readonly %x, i16* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i16_i16( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 8 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i16> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i16, i16* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i16, i16* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i16* [[TMP2]] to <8 x i16>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, <8 x i16>* [[TMP3]], align 2 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i16, i16* [[Y:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i16, i16* [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP6:%.*]] = bitcast i16* [[TMP5]] to <8 x i16>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <8 x i16>, <8 x i16>* [[TMP6]], align 2 +; CHECK-NEXT: [[TMP7:%.*]] = mul <8 x i16> [[WIDE_LOAD1]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP8]] = add <8 x i16> [[TMP7]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8 +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !20 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP10:%.*]] = call i16 @llvm.experimental.vector.reduce.add.v8i16(<8 x i16> [[TMP8]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i16 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_013:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_012:%.*]] = phi i16 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i16, i16* [[X]], i32 [[I_013]] +; CHECK-NEXT: [[TMP11:%.*]] = load i16, i16* [[ARRAYIDX]], align 2 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i16, i16* [[Y]], i32 [[I_013]] +; CHECK-NEXT: [[TMP12:%.*]] = load i16, i16* [[ARRAYIDX1]], align 2 +; CHECK-NEXT: [[MUL:%.*]] = mul i16 [[TMP12]], [[TMP11]] +; CHECK-NEXT: [[ADD]] = add i16 [[MUL]], [[R_012]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_013]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !21 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i16 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i16 [[R_0_LCSSA]] +; +entry: + %cmp11 = icmp sgt i32 %n, 0 + br i1 %cmp11, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.012 = phi i16 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i16, i16* %x, i32 %i.013 + %0 = load i16, i16* %arrayidx, align 2 + %arrayidx1 = getelementptr inbounds i16, i16* %y, i32 %i.013 + %1 = load i16, i16* %arrayidx1, align 2 + %mul = mul i16 %1, %0 + %add = add i16 %mul, %r.012 + %inc = add nuw nsw i32 %i.013, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ] + ret i16 %r.0.lcssa +} + +define signext i16 @mla_i8_i16(i8* nocapture readonly %x, i8* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i8_i16( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 8 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 8 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <8 x i16> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP10:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to <8 x i8>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[TMP3]], align 1 +; CHECK-NEXT: [[TMP4:%.*]] = zext <8 x i8> [[WIDE_LOAD]] to <8 x i16> +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, i8* [[Y:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, i8* [[TMP5]], i32 0 +; CHECK-NEXT: [[TMP7:%.*]] = bitcast i8* [[TMP6]] to <8 x i8>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <8 x i8>, <8 x i8>* [[TMP7]], align 1 +; CHECK-NEXT: [[TMP8:%.*]] = zext <8 x i8> [[WIDE_LOAD1]] to <8 x i16> +; CHECK-NEXT: [[TMP9:%.*]] = mul nuw <8 x i16> [[TMP8]], [[TMP4]] +; CHECK-NEXT: [[TMP10]] = add <8 x i16> [[TMP9]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8 +; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP11]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !22 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP12:%.*]] = call i16 @llvm.experimental.vector.reduce.add.v8i16(<8 x i16> [[TMP10]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i16 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP12]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_013:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_012:%.*]] = phi i16 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X]], i32 [[I_013]] +; CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[TMP13]] to i16 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[Y]], i32 [[I_013]] +; CHECK-NEXT: [[TMP14:%.*]] = load i8, i8* [[ARRAYIDX1]], align 1 +; CHECK-NEXT: [[CONV2:%.*]] = zext i8 [[TMP14]] to i16 +; CHECK-NEXT: [[MUL:%.*]] = mul nuw i16 [[CONV2]], [[CONV]] +; CHECK-NEXT: [[ADD]] = add i16 [[MUL]], [[R_012]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_013]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !23 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i16 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP12]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i16 [[R_0_LCSSA]] +; +entry: + %cmp11 = icmp sgt i32 %n, 0 + br i1 %cmp11, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.012 = phi i16 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i8, i8* %x, i32 %i.013 + %0 = load i8, i8* %arrayidx, align 1 + %conv = zext i8 %0 to i16 + %arrayidx1 = getelementptr inbounds i8, i8* %y, i32 %i.013 + %1 = load i8, i8* %arrayidx1, align 1 + %conv2 = zext i8 %1 to i16 + %mul = mul nuw i16 %conv2, %conv + %add = add i16 %mul, %r.012 + %inc = add nuw nsw i32 %i.013, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i16 [ 0, %entry ], [ %add, %for.body ] + ret i16 %r.0.lcssa +} + +define zeroext i8 @mla_i8_i8(i8* nocapture readonly %x, i8* nocapture readonly %y, i32 %n) #0 { +; CHECK-LABEL: @mla_i8_i8( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP10:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP10]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.body.preheader: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[N]], 16 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[N]], 16 +; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[N]], [[N_MOD_VF]] +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <16 x i8> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[INDEX]], 0 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[X:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[TMP1]], i32 0 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to <16 x i8>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <16 x i8>, <16 x i8>* [[TMP3]], align 1 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, i8* [[Y:%.*]], i32 [[TMP0]] +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, i8* [[TMP4]], i32 0 +; CHECK-NEXT: [[TMP6:%.*]] = bitcast i8* [[TMP5]] to <16 x i8>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <16 x i8>, <16 x i8>* [[TMP6]], align 1 +; CHECK-NEXT: [[TMP7:%.*]] = mul <16 x i8> [[WIDE_LOAD1]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP8]] = add <16 x i8> [[TMP7]], [[VEC_PHI]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 16 +; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !24 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP10:%.*]] = call i8 @llvm.experimental.vector.reduce.add.v16i8(<16 x i8> [[TMP8]]) +; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[N]], [[N_VEC]] +; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i32 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] +; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i8 [ 0, [[FOR_BODY_PREHEADER]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I_012:%.*]] = phi i32 [ [[INC:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[R_011:%.*]] = phi i8 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i8, i8* [[X]], i32 [[I_012]] +; CHECK-NEXT: [[TMP11:%.*]] = load i8, i8* [[ARRAYIDX]], align 1 +; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i8, i8* [[Y]], i32 [[I_012]] +; CHECK-NEXT: [[TMP12:%.*]] = load i8, i8* [[ARRAYIDX1]], align 1 +; CHECK-NEXT: [[MUL:%.*]] = mul i8 [[TMP12]], [[TMP11]] +; CHECK-NEXT: [[ADD]] = add i8 [[MUL]], [[R_011]] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_012]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !25 +; CHECK: for.cond.cleanup.loopexit: +; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i8 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[R_0_LCSSA:%.*]] = phi i8 [ 0, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_COND_CLEANUP_LOOPEXIT]] ] +; CHECK-NEXT: ret i8 [[R_0_LCSSA]] +; +entry: + %cmp10 = icmp sgt i32 %n, 0 + br i1 %cmp10, label %for.body, label %for.cond.cleanup + +for.body: ; preds = %entry, %for.body + %i.012 = phi i32 [ %inc, %for.body ], [ 0, %entry ] + %r.011 = phi i8 [ %add, %for.body ], [ 0, %entry ] + %arrayidx = getelementptr inbounds i8, i8* %x, i32 %i.012 + %0 = load i8, i8* %arrayidx, align 1 + %arrayidx1 = getelementptr inbounds i8, i8* %y, i32 %i.012 + %1 = load i8, i8* %arrayidx1, align 1 + %mul = mul i8 %1, %0 + %add = add i8 %mul, %r.011 + %inc = add nuw nsw i32 %i.012, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + %r.0.lcssa = phi i8 [ 0, %entry ], [ %add, %for.body ] + ret i8 %r.0.lcssa +} + +attributes #0 = { "target-features"="+mve" } diff --git a/llvm/test/Transforms/LoopVectorize/reduction-inloop-uf4.ll b/llvm/test/Transforms/LoopVectorize/reduction-inloop-uf4.ll new file mode 100644 index 0000000000000..013e08de44f08 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/reduction-inloop-uf4.ll @@ -0,0 +1,68 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -loop-vectorize -force-vector-interleave=4 -force-vector-width=4 -force-reduction-intrinsics -dce -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" + +define i32 @reduction_sum_single(i32* noalias nocapture %A) { +; CHECK-LABEL: @reduction_sum_single( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI1:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP9:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI2:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP10:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI3:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP11:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 4 +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD4:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 8 +; CHECK-NEXT: [[TMP5:%.*]] = bitcast i32* [[TMP4]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD5:%.*]] = load <4 x i32>, <4 x i32>* [[TMP5]], align 4 +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 12 +; CHECK-NEXT: [[TMP7:%.*]] = bitcast i32* [[TMP6]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD6:%.*]] = load <4 x i32>, <4 x i32>* [[TMP7]], align 4 +; CHECK-NEXT: [[TMP8]] = add <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP9]] = add <4 x i32> [[VEC_PHI1]], [[WIDE_LOAD4]] +; CHECK-NEXT: [[TMP10]] = add <4 x i32> [[VEC_PHI2]], [[WIDE_LOAD5]] +; CHECK-NEXT: [[TMP11]] = add <4 x i32> [[VEC_PHI3]], [[WIDE_LOAD6]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 16 +; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0 +; CHECK: middle.block: +; CHECK-NEXT: [[BIN_RDX:%.*]] = add <4 x i32> [[TMP9]], [[TMP8]] +; CHECK-NEXT: [[BIN_RDX7:%.*]] = add <4 x i32> [[TMP10]], [[BIN_RDX]] +; CHECK-NEXT: [[BIN_RDX8:%.*]] = add <4 x i32> [[TMP11]], [[BIN_RDX7]] +; CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[BIN_RDX8]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: br label [[DOTLR_PH:%.*]] +; CHECK: .lr.ph: +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !2 +; CHECK: ._crit_edge: +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP13]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] +; +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02 = phi i32 [ %l7, %.lr.ph ], [ 0, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l7 = add i32 %sum.02, %l3 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, 256 + br i1 %exitcond, label %._crit_edge, label %.lr.ph + +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l7, %.lr.ph ] + ret i32 %sum.0.lcssa +} diff --git a/llvm/test/Transforms/LoopVectorize/reduction-inloop.ll b/llvm/test/Transforms/LoopVectorize/reduction-inloop.ll index 0886b8eca2ef3..a6747fac8055e 100644 --- a/llvm/test/Transforms/LoopVectorize/reduction-inloop.ll +++ b/llvm/test/Transforms/LoopVectorize/reduction-inloop.ll @@ -3,1020 +3,785 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -define i32 @reduction_sum(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp { +define i32 @reduction_sum_single(i32* noalias nocapture %A) { +; CHECK-LABEL: @reduction_sum_single( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP2:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2]] = add <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP3]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP2]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: br label [[DOTLR_PH:%.*]] +; CHECK: .lr.ph: +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !2 +; CHECK: ._crit_edge: +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP4]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] +; +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02 = phi i32 [ %l7, %.lr.ph ], [ 0, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l7 = add i32 %sum.02, %l3 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, 256 + br i1 %exitcond, label %._crit_edge, label %.lr.ph + +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l7, %.lr.ph ] + ret i32 %sum.0.lcssa +} + +define i32 @reduction_sum(i32* noalias nocapture %A, i32* noalias nocapture %B) { ; CHECK-LABEL: @reduction_sum( -; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[TMP1]], label [[DOTLR_PH_PREHEADER:%.*]], label [[DOT_CRIT_EDGE:%.*]] -; CHECK: .lr.ph.preheader: -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP2]] to i64 -; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP2]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP4]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP11:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP6:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[VEC_IND2:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT3:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP8:%.*]] = bitcast i32* [[TMP7]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP8]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = add <4 x i32> [[VEC_PHI]], [[VEC_IND2]] -; CHECK-NEXT: [[TMP10:%.*]] = add <4 x i32> [[TMP9]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP11]] = add <4 x i32> [[TMP10]], [[WIDE_LOAD1]] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = add <4 x i32> [[VEC_PHI]], [[VEC_IND2]] +; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i32> [[TMP4]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP6]] = add <4 x i32> [[TMP5]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; CHECK-NEXT: [[VEC_IND_NEXT3]] = add <4 x i32> [[VEC_IND2]], -; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !4 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP11]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP4]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[DOT_CRIT_EDGE_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP6]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[DOTLR_PH_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP13]], [[MIDDLE_BLOCK]] ], [ 0, [[DOTLR_PH_PREHEADER]] ] ; CHECK-NEXT: br label [[DOTLR_PH:%.*]] ; CHECK: .lr.ph: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[DOTLR_PH]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[SUM_02:%.*]] = phi i32 [ [[TMP21:%.*]], [[DOTLR_PH]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[TMP14]], align 4 -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP16]], align 4 -; CHECK-NEXT: [[TMP18:%.*]] = trunc i64 [[INDVARS_IV]] to i32 -; CHECK-NEXT: [[TMP19:%.*]] = add i32 [[SUM_02]], [[TMP18]] -; CHECK-NEXT: [[TMP20:%.*]] = add i32 [[TMP19]], [[TMP15]] -; CHECK-NEXT: [[TMP21]] = add i32 [[TMP20]], [[TMP17]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[DOT_CRIT_EDGE_LOOPEXIT]], label [[DOTLR_PH]], !llvm.loop !2 -; CHECK: ._crit_edge.loopexit: -; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi i32 [ [[TMP21]], [[DOTLR_PH]] ], [ [[TMP13]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[DOT_CRIT_EDGE]] +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !5 ; CHECK: ._crit_edge: -; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[DOTLCSSA]], [[DOT_CRIT_EDGE_LOOPEXIT]] ] +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP8]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] ; - %1 = icmp sgt i32 %n, 0 - br i1 %1, label %.lr.ph, label %._crit_edge - -.lr.ph: ; preds = %0, %.lr.ph - %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ] - %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %0 ] - %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %3 = load i32, i32* %2, align 4 - %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %5 = load i32, i32* %4, align 4 - %6 = trunc i64 %indvars.iv to i32 - %7 = add i32 %sum.02, %6 - %8 = add i32 %7, %3 - %9 = add i32 %8, %5 +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02 = phi i32 [ %l9, %.lr.ph ], [ 0, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %l5 = load i32, i32* %l4, align 4 + %l6 = trunc i64 %indvars.iv to i32 + %l7 = add i32 %sum.02, %l6 + %l8 = add i32 %l7, %l3 + %l9 = add i32 %l8, %l5 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %._crit_edge, label %.lr.ph -._crit_edge: ; preds = %.lr.ph, %0 - %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ] +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l9, %.lr.ph ] ret i32 %sum.0.lcssa } -define i32 @reduction_prod(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp { +define i32 @reduction_sum_const(i32* noalias nocapture %A) { +; CHECK-LABEL: @reduction_sum_const( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP3:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = add <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP3]] = add <4 x i32> [[TMP2]], +; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP4]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !6 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP3]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: br label [[DOTLR_PH:%.*]] +; CHECK: .lr.ph: +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !7 +; CHECK: ._crit_edge: +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP5]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] +; +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02 = phi i32 [ %l9, %.lr.ph ], [ 0, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l7 = add i32 %sum.02, %l3 + %l9 = add i32 %l7, 3 + %indvars.iv.next = add i64 %indvars.iv, 1 + %lftr.wideiv = trunc i64 %indvars.iv.next to i32 + %exitcond = icmp eq i32 %lftr.wideiv, 256 + br i1 %exitcond, label %._crit_edge, label %.lr.ph + +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l9, %.lr.ph ] + ret i32 %sum.0.lcssa +} + +define i32 @reduction_prod(i32* noalias nocapture %A, i32* noalias nocapture %B) { ; CHECK-LABEL: @reduction_prod( -; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[TMP1]], label [[DOTLR_PH_PREHEADER:%.*]], label [[DOT_CRIT_EDGE:%.*]] -; CHECK: .lr.ph.preheader: -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP2]] to i64 -; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP2]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP4]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP11:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP6:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[VEC_IND2:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT3:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP8:%.*]] = bitcast i32* [[TMP7]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP8]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = mul <4 x i32> [[VEC_PHI]], [[VEC_IND2]] -; CHECK-NEXT: [[TMP10:%.*]] = mul <4 x i32> [[TMP9]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP11]] = mul <4 x i32> [[TMP10]], [[WIDE_LOAD1]] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = mul <4 x i32> [[VEC_PHI]], [[VEC_IND2]] +; CHECK-NEXT: [[TMP5:%.*]] = mul <4 x i32> [[TMP4]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP6]] = mul <4 x i32> [[TMP5]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; CHECK-NEXT: [[VEC_IND_NEXT3]] = add <4 x i32> [[VEC_IND2]], -; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !4 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !8 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.experimental.vector.reduce.mul.v4i32(<4 x i32> [[TMP11]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP4]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[DOT_CRIT_EDGE_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.experimental.vector.reduce.mul.v4i32(<4 x i32> [[TMP6]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[DOTLR_PH_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP13]], [[MIDDLE_BLOCK]] ], [ 1, [[DOTLR_PH_PREHEADER]] ] ; CHECK-NEXT: br label [[DOTLR_PH:%.*]] ; CHECK: .lr.ph: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[DOTLR_PH]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[PROD_02:%.*]] = phi i32 [ [[TMP21:%.*]], [[DOTLR_PH]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[TMP14]], align 4 -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP16]], align 4 -; CHECK-NEXT: [[TMP18:%.*]] = trunc i64 [[INDVARS_IV]] to i32 -; CHECK-NEXT: [[TMP19:%.*]] = mul i32 [[PROD_02]], [[TMP18]] -; CHECK-NEXT: [[TMP20:%.*]] = mul i32 [[TMP19]], [[TMP15]] -; CHECK-NEXT: [[TMP21]] = mul i32 [[TMP20]], [[TMP17]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[DOT_CRIT_EDGE_LOOPEXIT]], label [[DOTLR_PH]], !llvm.loop !5 -; CHECK: ._crit_edge.loopexit: -; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi i32 [ [[TMP21]], [[DOTLR_PH]] ], [ [[TMP13]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[DOT_CRIT_EDGE]] +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !9 ; CHECK: ._crit_edge: -; CHECK-NEXT: [[PROD_0_LCSSA:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ [[DOTLCSSA]], [[DOT_CRIT_EDGE_LOOPEXIT]] ] +; CHECK-NEXT: [[PROD_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP8]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[PROD_0_LCSSA]] ; - %1 = icmp sgt i32 %n, 0 - br i1 %1, label %.lr.ph, label %._crit_edge - -.lr.ph: ; preds = %0, %.lr.ph - %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ] - %prod.02 = phi i32 [ %9, %.lr.ph ], [ 1, %0 ] - %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %3 = load i32, i32* %2, align 4 - %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %5 = load i32, i32* %4, align 4 - %6 = trunc i64 %indvars.iv to i32 - %7 = mul i32 %prod.02, %6 - %8 = mul i32 %7, %3 - %9 = mul i32 %8, %5 +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %prod.02 = phi i32 [ %l9, %.lr.ph ], [ 1, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %l5 = load i32, i32* %l4, align 4 + %l6 = trunc i64 %indvars.iv to i32 + %l7 = mul i32 %prod.02, %l6 + %l8 = mul i32 %l7, %l3 + %l9 = mul i32 %l8, %l5 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %._crit_edge, label %.lr.ph -._crit_edge: ; preds = %.lr.ph, %0 - %prod.0.lcssa = phi i32 [ 1, %0 ], [ %9, %.lr.ph ] +._crit_edge: ; preds = %.lr.ph + %prod.0.lcssa = phi i32 [ %l9, %.lr.ph ] ret i32 %prod.0.lcssa } -define i32 @reduction_mix(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp { +define i32 @reduction_mix(i32* noalias nocapture %A, i32* noalias nocapture %B) { ; CHECK-LABEL: @reduction_mix( -; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[TMP1]], label [[DOTLR_PH_PREHEADER:%.*]], label [[DOT_CRIT_EDGE:%.*]] -; CHECK: .lr.ph.preheader: -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP2]] to i64 -; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP2]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP4]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP11:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP6:%.*]], [[VECTOR_BODY]] ] ; CHECK-NEXT: [[VEC_IND2:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT3:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP8:%.*]] = bitcast i32* [[TMP7]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP8]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = mul nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP10:%.*]] = add <4 x i32> [[VEC_PHI]], [[VEC_IND2]] -; CHECK-NEXT: [[TMP11]] = add <4 x i32> [[TMP10]], [[TMP9]] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = mul nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i32> [[VEC_PHI]], [[VEC_IND2]] +; CHECK-NEXT: [[TMP6]] = add <4 x i32> [[TMP5]], [[TMP4]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; CHECK-NEXT: [[VEC_IND_NEXT3]] = add <4 x i32> [[VEC_IND2]], -; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !6 +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !10 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP11]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP4]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[DOT_CRIT_EDGE_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP6]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[DOTLR_PH_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP13]], [[MIDDLE_BLOCK]] ], [ 0, [[DOTLR_PH_PREHEADER]] ] ; CHECK-NEXT: br label [[DOTLR_PH:%.*]] ; CHECK: .lr.ph: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[DOTLR_PH]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[SUM_02:%.*]] = phi i32 [ [[TMP21:%.*]], [[DOTLR_PH]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[TMP14]], align 4 -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP16]], align 4 -; CHECK-NEXT: [[TMP18:%.*]] = mul nsw i32 [[TMP17]], [[TMP15]] -; CHECK-NEXT: [[TMP19:%.*]] = trunc i64 [[INDVARS_IV]] to i32 -; CHECK-NEXT: [[TMP20:%.*]] = add i32 [[SUM_02]], [[TMP19]] -; CHECK-NEXT: [[TMP21]] = add i32 [[TMP20]], [[TMP18]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[DOT_CRIT_EDGE_LOOPEXIT]], label [[DOTLR_PH]], !llvm.loop !7 -; CHECK: ._crit_edge.loopexit: -; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi i32 [ [[TMP21]], [[DOTLR_PH]] ], [ [[TMP13]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[DOT_CRIT_EDGE]] +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !11 ; CHECK: ._crit_edge: -; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[DOTLCSSA]], [[DOT_CRIT_EDGE_LOOPEXIT]] ] +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP8]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] ; - %1 = icmp sgt i32 %n, 0 - br i1 %1, label %.lr.ph, label %._crit_edge - -.lr.ph: ; preds = %0, %.lr.ph - %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ] - %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %0 ] - %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %3 = load i32, i32* %2, align 4 - %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %5 = load i32, i32* %4, align 4 - %6 = mul nsw i32 %5, %3 - %7 = trunc i64 %indvars.iv to i32 - %8 = add i32 %sum.02, %7 - %9 = add i32 %8, %6 +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02 = phi i32 [ %l9, %.lr.ph ], [ 0, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %l5 = load i32, i32* %l4, align 4 + %l6 = mul nsw i32 %l5, %l3 + %l7 = trunc i64 %indvars.iv to i32 + %l8 = add i32 %sum.02, %l7 + %l9 = add i32 %l8, %l6 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %._crit_edge, label %.lr.ph -._crit_edge: ; preds = %.lr.ph, %0 - %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ] +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l9, %.lr.ph ] ret i32 %sum.0.lcssa } -define i32 @reduction_mul(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp { +define i32 @reduction_mul(i32* noalias nocapture %A, i32* noalias nocapture %B) { ; CHECK-LABEL: @reduction_mul( -; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[TMP1]], label [[DOTLR_PH_PREHEADER:%.*]], label [[DOT_CRIT_EDGE:%.*]] -; CHECK: .lr.ph.preheader: -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP2]] to i64 -; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP2]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP4]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP10:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP8:%.*]] = bitcast i32* [[TMP7]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP8]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = mul <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP10]] = mul <4 x i32> [[TMP9]], [[WIDE_LOAD1]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = mul <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP5]] = mul <4 x i32> [[TMP4]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP11:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP11]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !8 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !12 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP12:%.*]] = call i32 @llvm.experimental.vector.reduce.mul.v4i32(<4 x i32> [[TMP10]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP4]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[DOT_CRIT_EDGE_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.experimental.vector.reduce.mul.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[DOTLR_PH_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP12]], [[MIDDLE_BLOCK]] ], [ 19, [[DOTLR_PH_PREHEADER]] ] ; CHECK-NEXT: br label [[DOTLR_PH:%.*]] ; CHECK: .lr.ph: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[DOTLR_PH]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[SUM_02:%.*]] = phi i32 [ [[TMP18:%.*]], [[DOTLR_PH]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP14:%.*]] = load i32, i32* [[TMP13]], align 4 -; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* [[TMP15]], align 4 -; CHECK-NEXT: [[TMP17:%.*]] = mul i32 [[SUM_02]], [[TMP14]] -; CHECK-NEXT: [[TMP18]] = mul i32 [[TMP17]], [[TMP16]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[DOT_CRIT_EDGE_LOOPEXIT]], label [[DOTLR_PH]], !llvm.loop !9 -; CHECK: ._crit_edge.loopexit: -; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi i32 [ [[TMP18]], [[DOTLR_PH]] ], [ [[TMP12]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[DOT_CRIT_EDGE]] +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !13 ; CHECK: ._crit_edge: -; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[DOTLCSSA]], [[DOT_CRIT_EDGE_LOOPEXIT]] ] +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] ; - %1 = icmp sgt i32 %n, 0 - br i1 %1, label %.lr.ph, label %._crit_edge - -.lr.ph: ; preds = %0, %.lr.ph - %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ] - %sum.02 = phi i32 [ %7, %.lr.ph ], [ 19, %0 ] - %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %3 = load i32, i32* %2, align 4 - %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %5 = load i32, i32* %4, align 4 - %6 = mul i32 %sum.02, %3 - %7 = mul i32 %6, %5 +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02 = phi i32 [ %l7, %.lr.ph ], [ 19, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %l5 = load i32, i32* %l4, align 4 + %l6 = mul i32 %sum.02, %l3 + %l7 = mul i32 %l6, %l5 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %._crit_edge, label %.lr.ph -._crit_edge: ; preds = %.lr.ph, %0 - %sum.0.lcssa = phi i32 [ 0, %0 ], [ %7, %.lr.ph ] +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l7, %.lr.ph ] ret i32 %sum.0.lcssa } -define i32 @start_at_non_zero(i32* nocapture %in, i32* nocapture %coeff, i32* nocapture %out, i32 %n) nounwind uwtable readonly ssp { +define i32 @start_at_non_zero(i32* nocapture %in, i32* nocapture %coeff, i32* nocapture %out) { ; CHECK-LABEL: @start_at_non_zero( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, i32* [[IN:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP3]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[COEFF:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = mul nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP8]] = add <4 x i32> [[TMP7]], [[VEC_PHI]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[IN:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[COEFF:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = mul nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP5]] = add <4 x i32> [[TMP4]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !10 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !14 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP10:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP8]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP10]], [[MIDDLE_BLOCK]] ], [ 120, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[SUM_09:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[IN]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[COEFF]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4 -; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP12]], [[TMP11]] -; CHECK-NEXT: [[ADD]] = add nsw i32 [[MUL]], [[SUM_09]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !11 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[ADD_LCSSA:%.*]] = phi i32 [ [[ADD]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !15 ; CHECK: for.end: -; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 120, [[ENTRY:%.*]] ], [ [[ADD_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] ; entry: - %cmp7 = icmp sgt i32 %n, 0 - br i1 %cmp7, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %sum.09 = phi i32 [ %add, %for.body ], [ 120, %entry ] %arrayidx = getelementptr inbounds i32, i32* %in, i64 %indvars.iv - %0 = load i32, i32* %arrayidx, align 4 + %l0 = load i32, i32* %arrayidx, align 4 %arrayidx2 = getelementptr inbounds i32, i32* %coeff, i64 %indvars.iv - %1 = load i32, i32* %arrayidx2, align 4 - %mul = mul nsw i32 %1, %0 + %l1 = load i32, i32* %arrayidx2, align 4 + %mul = mul nsw i32 %l1, %l0 %add = add nsw i32 %mul, %sum.09 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %sum.0.lcssa = phi i32 [ 120, %entry ], [ %add, %for.body ] + %sum.0.lcssa = phi i32 [ %add, %for.body ] ret i32 %sum.0.lcssa } -define i32 @reduction_and(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly { +define i32 @reduction_and(i32* nocapture %A, i32* nocapture %B) { ; CHECK-LABEL: @reduction_and( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP3]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = and <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP8]] = and <4 x i32> [[TMP7]], [[WIDE_LOAD1]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = and <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP5]] = and <4 x i32> [[TMP4]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !12 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !16 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP10:%.*]] = call i32 @llvm.experimental.vector.reduce.and.v4i32(<4 x i32> [[TMP8]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.experimental.vector.reduce.and.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP10]], [[MIDDLE_BLOCK]] ], [ -1, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[RESULT_08:%.*]] = phi i32 [ [[AND:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4 -; CHECK-NEXT: [[ADD:%.*]] = and i32 [[RESULT_08]], [[TMP11]] -; CHECK-NEXT: [[AND]] = and i32 [[ADD]], [[TMP12]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !13 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[AND_LCSSA:%.*]] = phi i32 [ [[AND]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !17 ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ -1, [[ENTRY:%.*]] ], [ [[AND_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ undef, [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[RESULT_0_LCSSA]] ; entry: - %cmp7 = icmp sgt i32 %n, 0 - br i1 %cmp7, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %result.08 = phi i32 [ %and, %for.body ], [ -1, %entry ] %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %0 = load i32, i32* %arrayidx, align 4 + %l0 = load i32, i32* %arrayidx, align 4 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %1 = load i32, i32* %arrayidx2, align 4 - %add = and i32 %result.08, %0 - %and = and i32 %add, %1 + %l1 = load i32, i32* %arrayidx2, align 4 + %add = and i32 %result.08, %l0 + %and = and i32 %add, %l1 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %result.0.lcssa = phi i32 [ -1, %entry ], [ %and, %for.body ] + %result.0.lcssa = phi i32 [ %and, %for.body ] ret i32 %result.0.lcssa } -define i32 @reduction_or(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly { +define i32 @reduction_or(i32* nocapture %A, i32* nocapture %B) { ; CHECK-LABEL: @reduction_or( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP3]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = add nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP8]] = or <4 x i32> [[TMP7]], [[VEC_PHI]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = add nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP5]] = or <4 x i32> [[TMP4]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !14 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !18 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP10:%.*]] = call i32 @llvm.experimental.vector.reduce.or.v4i32(<4 x i32> [[TMP8]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.experimental.vector.reduce.or.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP10]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[RESULT_08:%.*]] = phi i32 [ [[OR:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP12]], [[TMP11]] -; CHECK-NEXT: [[OR]] = or i32 [[ADD]], [[RESULT_08]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !15 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[OR_LCSSA:%.*]] = phi i32 [ [[OR]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !19 ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[OR_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ undef, [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[RESULT_0_LCSSA]] ; entry: - %cmp7 = icmp sgt i32 %n, 0 - br i1 %cmp7, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %result.08 = phi i32 [ %or, %for.body ], [ 0, %entry ] %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %0 = load i32, i32* %arrayidx, align 4 + %l0 = load i32, i32* %arrayidx, align 4 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %1 = load i32, i32* %arrayidx2, align 4 - %add = add nsw i32 %1, %0 + %l1 = load i32, i32* %arrayidx2, align 4 + %add = add nsw i32 %l1, %l0 %or = or i32 %add, %result.08 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %result.0.lcssa = phi i32 [ 0, %entry ], [ %or, %for.body ] + %result.0.lcssa = phi i32 [ %or, %for.body ] ret i32 %result.0.lcssa } -define i32 @reduction_xor(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly { +define i32 @reduction_xor(i32* nocapture %A, i32* nocapture %B) { ; CHECK-LABEL: @reduction_xor( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP3]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = add nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP8]] = xor <4 x i32> [[TMP7]], [[VEC_PHI]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = add nsw <4 x i32> [[WIDE_LOAD1]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP5]] = xor <4 x i32> [[TMP4]], [[VEC_PHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !16 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !20 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP10:%.*]] = call i32 @llvm.experimental.vector.reduce.xor.v4i32(<4 x i32> [[TMP8]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.experimental.vector.reduce.xor.v4i32(<4 x i32> [[TMP5]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP10]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[RESULT_08:%.*]] = phi i32 [ [[XOR:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP11:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP12:%.*]] = load i32, i32* [[ARRAYIDX2]], align 4 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP12]], [[TMP11]] -; CHECK-NEXT: [[XOR]] = xor i32 [[ADD]], [[RESULT_08]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !17 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[XOR_LCSSA:%.*]] = phi i32 [ [[XOR]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !21 ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[XOR_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ undef, [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[RESULT_0_LCSSA]] ; entry: - %cmp7 = icmp sgt i32 %n, 0 - br i1 %cmp7, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %result.08 = phi i32 [ %xor, %for.body ], [ 0, %entry ] %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %0 = load i32, i32* %arrayidx, align 4 + %l0 = load i32, i32* %arrayidx, align 4 %arrayidx2 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %1 = load i32, i32* %arrayidx2, align 4 - %add = add nsw i32 %1, %0 + %l1 = load i32, i32* %arrayidx2, align 4 + %add = add nsw i32 %l1, %l0 %xor = xor i32 %add, %result.08 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %result.0.lcssa = phi i32 [ 0, %entry ], [ %xor, %for.body ] + %result.0.lcssa = phi i32 [ %xor, %for.body ] ret i32 %result.0.lcssa } -define float @reduction_fadd(i32 %n, float* nocapture %A, float* nocapture %B) nounwind uwtable readonly { +define float @reduction_fadd(float* nocapture %A, float* nocapture %B) { ; CHECK-LABEL: @reduction_fadd( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds float, float* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast float* [[TMP3]] to <4 x float>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, <4 x float>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds float, float* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast float* [[TMP5]] to <4 x float>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, <4 x float>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = fadd fast <4 x float> [[VEC_PHI]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP8]] = fadd fast <4 x float> [[TMP7]], [[WIDE_LOAD1]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds float, float* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast float* [[TMP0]] to <4 x float>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds float, float* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast float* [[TMP2]] to <4 x float>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = fadd fast <4 x float> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP5]] = fadd fast <4 x float> [[TMP4]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !18 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !22 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP10:%.*]] = call fast float @llvm.experimental.vector.reduce.v2.fadd.f32.v4f32(float 0.000000e+00, <4 x float> [[TMP8]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP7:%.*]] = call fast float @llvm.experimental.vector.reduce.v2.fadd.f32.v4f32(float 0.000000e+00, <4 x float> [[TMP5]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP10]], [[MIDDLE_BLOCK]] ], [ 0.000000e+00, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[RESULT_08:%.*]] = phi float [ [[FADD:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds float, float* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[ARRAYIDX2]], align 4 -; CHECK-NEXT: [[ADD:%.*]] = fadd fast float [[RESULT_08]], [[TMP11]] -; CHECK-NEXT: [[FADD]] = fadd fast float [[ADD]], [[TMP12]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !19 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[FADD_LCSSA:%.*]] = phi float [ [[FADD]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !23 ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[FADD_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi float [ undef, [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[RESULT_0_LCSSA]] ; entry: - %cmp7 = icmp sgt i32 %n, 0 - br i1 %cmp7, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %result.08 = phi float [ %fadd, %for.body ], [ 0.0, %entry ] %arrayidx = getelementptr inbounds float, float* %A, i64 %indvars.iv - %0 = load float, float* %arrayidx, align 4 + %l0 = load float, float* %arrayidx, align 4 %arrayidx2 = getelementptr inbounds float, float* %B, i64 %indvars.iv - %1 = load float, float* %arrayidx2, align 4 - %add = fadd fast float %result.08, %0 - %fadd = fadd fast float %add, %1 + %l1 = load float, float* %arrayidx2, align 4 + %add = fadd fast float %result.08, %l0 + %fadd = fadd fast float %add, %l1 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %result.0.lcssa = phi float [ 0.0, %entry ], [ %fadd, %for.body ] + %result.0.lcssa = phi float [ %fadd, %for.body ] ret float %result.0.lcssa } -define float @reduction_fmul(i32 %n, float* nocapture %A, float* nocapture %B) nounwind uwtable readonly { +define float @reduction_fmul(float* nocapture %A, float* nocapture %B) { ; CHECK-LABEL: @reduction_fmul( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ , [[VECTOR_PH]] ], [ [[TMP8:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds float, float* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast float* [[TMP3]] to <4 x float>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, <4 x float>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds float, float* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast float* [[TMP5]] to <4 x float>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, <4 x float>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = fmul fast <4 x float> [[VEC_PHI]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP8]] = fmul fast <4 x float> [[TMP7]], [[WIDE_LOAD1]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x float> [ , [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds float, float* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast float* [[TMP0]] to <4 x float>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x float>, <4 x float>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds float, float* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast float* [[TMP2]] to <4 x float>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x float>, <4 x float>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = fmul fast <4 x float> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP5]] = fmul fast <4 x float> [[TMP4]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP9]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !20 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !24 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP10:%.*]] = call fast float @llvm.experimental.vector.reduce.v2.fmul.f32.v4f32(float 1.000000e+00, <4 x float> [[TMP8]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP7:%.*]] = call fast float @llvm.experimental.vector.reduce.v2.fmul.f32.v4f32(float 1.000000e+00, <4 x float> [[TMP5]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi float [ [[TMP10]], [[MIDDLE_BLOCK]] ], [ 0.000000e+00, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[RESULT_08:%.*]] = phi float [ [[FMUL:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP11:%.*]] = load float, float* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds float, float* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP12:%.*]] = load float, float* [[ARRAYIDX2]], align 4 -; CHECK-NEXT: [[ADD:%.*]] = fmul fast float [[RESULT_08]], [[TMP11]] -; CHECK-NEXT: [[FMUL]] = fmul fast float [[ADD]], [[TMP12]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !21 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[FMUL_LCSSA:%.*]] = phi float [ [[FMUL]], [[FOR_BODY]] ], [ [[TMP10]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !25 ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[FMUL_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi float [ undef, [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[RESULT_0_LCSSA]] ; entry: - %cmp7 = icmp sgt i32 %n, 0 - br i1 %cmp7, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %result.08 = phi float [ %fmul, %for.body ], [ 0.0, %entry ] %arrayidx = getelementptr inbounds float, float* %A, i64 %indvars.iv - %0 = load float, float* %arrayidx, align 4 + %l0 = load float, float* %arrayidx, align 4 %arrayidx2 = getelementptr inbounds float, float* %B, i64 %indvars.iv - %1 = load float, float* %arrayidx2, align 4 - %add = fmul fast float %result.08, %0 - %fmul = fmul fast float %add, %1 + %l1 = load float, float* %arrayidx2, align 4 + %add = fmul fast float %result.08, %l0 + %fmul = fmul fast float %add, %l1 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %result.0.lcssa = phi float [ 0.0, %entry ], [ %fmul, %for.body ] + %result.0.lcssa = phi float [ %fmul, %for.body ] ret float %result.0.lcssa } -define i32 @reduction_min(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly { +define i32 @reduction_min(i32* nocapture %A, i32* nocapture %B) { ; CHECK-LABEL: @reduction_min( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP6:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP3]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = icmp slt <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP6]] = select <4 x i1> [[TMP5]], <4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP3:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP3]] = select <4 x i1> [[TMP2]], <4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !22 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP4]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !26 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.experimental.vector.reduce.smin.v4i32(<4 x i32> [[TMP6]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.experimental.vector.reduce.smin.v4i32(<4 x i32> [[TMP3]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP8]], [[MIDDLE_BLOCK]] ], [ 1000, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[RESULT_08:%.*]] = phi i32 [ [[V0:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[C0:%.*]] = icmp slt i32 [[RESULT_08]], [[TMP9]] -; CHECK-NEXT: [[V0]] = select i1 [[C0]], i32 [[RESULT_08]], i32 [[TMP9]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !23 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[V0_LCSSA:%.*]] = phi i32 [ [[V0]], [[FOR_BODY]] ], [ [[TMP8]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !27 ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[V0_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ undef, [[FOR_BODY]] ], [ [[TMP5]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[RESULT_0_LCSSA]] ; entry: - %cmp7 = icmp sgt i32 %n, 0 - br i1 %cmp7, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %result.08 = phi i32 [ %v0, %for.body ], [ 1000, %entry ] %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %0 = load i32, i32* %arrayidx, align 4 - %c0 = icmp slt i32 %result.08, %0 - %v0 = select i1 %c0, i32 %result.08, i32 %0 + %l0 = load i32, i32* %arrayidx, align 4 + %c0 = icmp slt i32 %result.08, %l0 + %v0 = select i1 %c0, i32 %result.08, i32 %l0 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %result.0.lcssa = phi i32 [ 0, %entry ], [ %v0, %for.body ] + %result.0.lcssa = phi i32 [ %v0, %for.body ] ret i32 %result.0.lcssa } -define i32 @reduction_max(i32 %n, i32* nocapture %A, i32* nocapture %B) nounwind uwtable readonly { +define i32 @reduction_max(i32* nocapture %A, i32* nocapture %B) { ; CHECK-LABEL: @reduction_max( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP7:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP7]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP6:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP3]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5:%.*]] = icmp ugt <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP6]] = select <4 x i1> [[TMP5]], <4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP3:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ugt <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP3]] = select <4 x i1> [[TMP2]], <4 x i32> [[VEC_PHI]], <4 x i32> [[WIDE_LOAD]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !24 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP4]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !28 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.experimental.vector.reduce.umax.v4i32(<4 x i32> [[TMP6]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.experimental.vector.reduce.umax.v4i32(<4 x i32> [[TMP3]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP8]], [[MIDDLE_BLOCK]] ], [ 1000, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[RESULT_08:%.*]] = phi i32 [ [[V0:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP9:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[C0:%.*]] = icmp ugt i32 [[RESULT_08]], [[TMP9]] -; CHECK-NEXT: [[V0]] = select i1 [[C0]], i32 [[RESULT_08]], i32 [[TMP9]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !25 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[V0_LCSSA:%.*]] = phi i32 [ [[V0]], [[FOR_BODY]] ], [ [[TMP8]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !29 ; CHECK: for.end: -; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[V0_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[RESULT_0_LCSSA:%.*]] = phi i32 [ undef, [[FOR_BODY]] ], [ [[TMP5]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[RESULT_0_LCSSA]] ; entry: - %cmp7 = icmp sgt i32 %n, 0 - br i1 %cmp7, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %result.08 = phi i32 [ %v0, %for.body ], [ 1000, %entry ] %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %0 = load i32, i32* %arrayidx, align 4 - %c0 = icmp ugt i32 %result.08, %0 - %v0 = select i1 %c0, i32 %result.08, i32 %0 + %l0 = load i32, i32* %arrayidx, align 4 + %c0 = icmp ugt i32 %result.08, %l0 + %v0 = select i1 %c0, i32 %result.08, i32 %l0 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %result.0.lcssa = phi i32 [ 0, %entry ], [ %v0, %for.body ] + %result.0.lcssa = phi i32 [ %v0, %for.body ] ret i32 %result.0.lcssa } ; Sub we can create a reduction, but not inloop -define i32 @reduction_sub_lhs(i32 %n, i32* noalias nocapture %A) nounwind uwtable readonly { +define i32 @reduction_sub_lhs(i32* noalias nocapture %A) { ; CHECK-LABEL: @reduction_sub_lhs( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP4:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[CMP4]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body.preheader: -; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[TMP0]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP2]], 8589934588 ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: ; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP5:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP4:%.*]] = bitcast i32* [[TMP3]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP4]], align 4 -; CHECK-NEXT: [[TMP5]] = sub <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP2:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2]] = sub <4 x i32> [[VEC_PHI]], [[WIDE_LOAD]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !26 +; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP3]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !30 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP7:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP5]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP2]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[FOR_END_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP2]]) +; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP7]], [[MIDDLE_BLOCK]] ], [ 0, [[FOR_BODY_PREHEADER]] ] ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[X_05:%.*]] = phi i32 [ [[SUB:%.*]], [[FOR_BODY]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP8:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[SUB]] = sub nsw i32 [[X_05]], [[TMP8]] -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT]], label [[FOR_BODY]], !llvm.loop !27 -; CHECK: for.end.loopexit: -; CHECK-NEXT: [[SUB_LCSSA:%.*]] = phi i32 [ [[SUB]], [[FOR_BODY]] ], [ [[TMP7]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[FOR_END]] +; CHECK-NEXT: br i1 undef, label [[FOR_END]], label [[FOR_BODY]], !llvm.loop !31 ; CHECK: for.end: -; CHECK-NEXT: [[X_0_LCSSA:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[SUB_LCSSA]], [[FOR_END_LOOPEXIT]] ] +; CHECK-NEXT: [[X_0_LCSSA:%.*]] = phi i32 [ undef, [[FOR_BODY]] ], [ [[TMP4]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[X_0_LCSSA]] ; entry: - %cmp4 = icmp sgt i32 %n, 0 - br i1 %cmp4, label %for.body, label %for.end + br label %for.body for.body: ; preds = %entry, %for.body %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %entry ] %x.05 = phi i32 [ %sub, %for.body ], [ 0, %entry ] %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %0 = load i32, i32* %arrayidx, align 4 - %sub = sub nsw i32 %x.05, %0 + %l0 = load i32, i32* %arrayidx, align 4 + %sub = sub nsw i32 %x.05, %l0 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %for.end, label %for.body for.end: ; preds = %for.body, %entry - %x.0.lcssa = phi i32 [ 0, %entry ], [ %sub, %for.body ] + %x.0.lcssa = phi i32 [ %sub, %for.body ] ret i32 %x.0.lcssa } @@ -1051,7 +816,7 @@ define float @reduction_conditional(float* %A, float* %B, float* %C, float %S) { ; CHECK-NEXT: [[PREDPHI3]] = select <4 x i1> [[TMP13]], <4 x float> [[VEC_PHI]], <4 x float> [[PREDPHI]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 ; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i64 [[INDEX_NEXT]], 128 -; CHECK-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !28 +; CHECK-NEXT: br i1 [[TMP14]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !32 ; CHECK: middle.block: ; CHECK-NEXT: [[TMP15:%.*]] = call fast float @llvm.experimental.vector.reduce.v2.fadd.f32.v4f32(float 0.000000e+00, <4 x float> [[PREDPHI3]]) ; CHECK-NEXT: br i1 true, label [[FOR_END:%.*]], label [[SCALAR_PH]] @@ -1068,7 +833,7 @@ define float @reduction_conditional(float* %A, float* %B, float* %C, float %S) { ; CHECK: if.then16: ; CHECK-NEXT: br label [[FOR_INC]] ; CHECK: for.inc: -; CHECK-NEXT: br i1 undef, label [[FOR_BODY]], label [[FOR_END]], !llvm.loop !29 +; CHECK-NEXT: br i1 undef, label [[FOR_BODY]], label [[FOR_END]], !llvm.loop !33 ; CHECK: for.end: ; CHECK-NEXT: [[SUM_1_LCSSA:%.*]] = phi float [ undef, [[FOR_INC]] ], [ [[TMP15]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret float [[SUM_1_LCSSA]] @@ -1080,26 +845,26 @@ for.body: %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.inc ] %sum.033 = phi float [ %S, %entry ], [ %sum.1, %for.inc ] %arrayidx = getelementptr inbounds float, float* %A, i64 %indvars.iv - %0 = load float, float* %arrayidx, align 4 + %l0 = load float, float* %arrayidx, align 4 %arrayidx2 = getelementptr inbounds float, float* %B, i64 %indvars.iv - %1 = load float, float* %arrayidx2, align 4 - %cmp3 = fcmp ogt float %0, %1 + %l1 = load float, float* %arrayidx2, align 4 + %cmp3 = fcmp ogt float %l0, %l1 br i1 %cmp3, label %if.then, label %for.inc if.then: - %cmp6 = fcmp ogt float %1, 1.000000e+00 + %cmp6 = fcmp ogt float %l1, 1.000000e+00 br i1 %cmp6, label %if.then8, label %if.else if.then8: - %add = fadd fast float %sum.033, %0 + %add = fadd fast float %sum.033, %l0 br label %for.inc if.else: - %cmp14 = fcmp ogt float %0, 2.000000e+00 + %cmp14 = fcmp ogt float %l0, 2.000000e+00 br i1 %cmp14, label %if.then16, label %for.inc if.then16: - %add19 = fadd fast float %sum.033, %1 + %add19 = fadd fast float %sum.033, %l1 br label %for.inc for.inc: @@ -1114,245 +879,211 @@ for.end: ret float %sum.1.lcssa } -define i32 @reduction_sum_multiuse(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) { +define i32 @reduction_sum_multiuse(i32* noalias nocapture %A, i32* noalias nocapture %B) { ; CHECK-LABEL: @reduction_sum_multiuse( -; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[TMP1]], label [[DOTLR_PH_PREHEADER:%.*]], label [[END:%.*]] -; CHECK: .lr.ph.preheader: -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP2]] to i64 -; CHECK-NEXT: [[TMP4:%.*]] = add nuw nsw i64 [[TMP3]], 1 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP2]], 3 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] -; CHECK: vector.ph: -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[TMP4]], 8589934588 -; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] -; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP11:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[VEC_IND2:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT3:%.*]], [[VECTOR_BODY]] ] -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP6]], align 4 -; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP8:%.*]] = bitcast i32* [[TMP7]] to <4 x i32>* -; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP8]], align 4 -; CHECK-NEXT: [[TMP9:%.*]] = add <4 x i32> [[VEC_PHI]], [[VEC_IND2]] -; CHECK-NEXT: [[TMP10:%.*]] = add <4 x i32> [[TMP9]], [[WIDE_LOAD]] -; CHECK-NEXT: [[TMP11]] = add <4 x i32> [[TMP10]], [[WIDE_LOAD1]] -; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[VEC_IND_NEXT3]] = add <4 x i32> [[VEC_IND2]], -; CHECK-NEXT: [[TMP12:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP12]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !30 -; CHECK: middle.block: -; CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP11]]) -; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i64 [[TMP4]], [[N_VEC]] -; CHECK-NEXT: br i1 [[CMP_N]], label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] -; CHECK: scalar.ph: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], [[MIDDLE_BLOCK]] ], [ 0, [[DOTLR_PH_PREHEADER]] ] -; CHECK-NEXT: [[BC_MERGE_RDX:%.*]] = phi i32 [ [[TMP13]], [[MIDDLE_BLOCK]] ], [ 0, [[DOTLR_PH_PREHEADER]] ] +; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[DOTLR_PH:%.*]] ; CHECK: .lr.ph: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[DOTLR_PH]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[SUM_02:%.*]] = phi i32 [ [[TMP21:%.*]], [[DOTLR_PH]] ], [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ] -; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[TMP14]], align 4 -; CHECK-NEXT: [[TMP16:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP16]], align 4 -; CHECK-NEXT: [[TMP18:%.*]] = trunc i64 [[INDVARS_IV]] to i32 -; CHECK-NEXT: [[TMP19:%.*]] = add i32 [[SUM_02]], [[TMP18]] -; CHECK-NEXT: [[TMP20:%.*]] = add i32 [[TMP19]], [[TMP15]] -; CHECK-NEXT: [[TMP21]] = add i32 [[TMP20]], [[TMP17]] +; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[DOTLR_PH]] ], [ 0, [[ENTRY:%.*]] ] +; CHECK-NEXT: [[SUM_02:%.*]] = phi i32 [ [[L10:%.*]], [[DOTLR_PH]] ], [ 0, [[ENTRY]] ] +; CHECK-NEXT: [[L2:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] +; CHECK-NEXT: [[L3:%.*]] = load i32, i32* [[L2]], align 4 +; CHECK-NEXT: [[L6:%.*]] = trunc i64 [[INDVARS_IV]] to i32 +; CHECK-NEXT: [[L7:%.*]] = add i32 [[SUM_02]], [[L6]] +; CHECK-NEXT: [[L8:%.*]] = add i32 [[L7]], [[L3]] +; CHECK-NEXT: [[L10]] = add i32 [[L8]], [[SUM_02]] ; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 ; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]] -; CHECK-NEXT: br i1 [[EXITCOND]], label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !31 -; CHECK: ._crit_edge: -; CHECK-NEXT: [[SUM_LCSSA:%.*]] = phi i32 [ [[TMP21]], [[DOTLR_PH]] ], [ [[TMP13]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: [[SUM_COPY:%.*]] = phi i32 [ [[TMP21]], [[DOTLR_PH]] ], [ [[TMP13]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[END]] +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], 256 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[END:%.*]], label [[DOTLR_PH]] ; CHECK: end: -; CHECK-NEXT: [[F1:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[SUM_LCSSA]], [[DOT_CRIT_EDGE]] ] -; CHECK-NEXT: [[F2:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[SUM_COPY]], [[DOT_CRIT_EDGE]] ] -; CHECK-NEXT: [[FINAL:%.*]] = add i32 [[F1]], [[F2]] -; CHECK-NEXT: ret i32 [[FINAL]] +; CHECK-NEXT: ret i32 [[L10]] ; - %1 = icmp sgt i32 %n, 0 - br i1 %1, label %.lr.ph.preheader, label %end -.lr.ph.preheader: ; preds = %0 +entry: br label %.lr.ph -.lr.ph: ; preds = %0, %.lr.ph - %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %.lr.ph.preheader ] - %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %.lr.ph.preheader ] - %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %3 = load i32, i32* %2, align 4 - %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %5 = load i32, i32* %4, align 4 - %6 = trunc i64 %indvars.iv to i32 - %7 = add i32 %sum.02, %6 - %8 = add i32 %7, %3 - %9 = add i32 %8, %5 +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02 = phi i32 [ %l10, %.lr.ph ], [ 0, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %l5 = load i32, i32* %l4, align 4 + %l6 = trunc i64 %indvars.iv to i32 + %l7 = add i32 %sum.02, %l6 + %l8 = add i32 %l7, %l3 + %l9 = add i32 %l8, %l5 + %l10 = add i32 %l8, %sum.02 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n - br i1 %exitcond, label %._crit_edge, label %.lr.ph - -._crit_edge: ; preds = %.lr.ph, %0 - %sum.lcssa = phi i32 [ %9, %.lr.ph ] - %sum.copy = phi i32 [ %9, %.lr.ph ] - br label %end + %exitcond = icmp eq i32 %lftr.wideiv, 256 + br i1 %exitcond, label %end, label %.lr.ph end: - %f1 = phi i32 [ 0, %0 ], [ %sum.lcssa, %._crit_edge ] - %f2 = phi i32 [ 0, %0 ], [ %sum.copy, %._crit_edge ] - %final = add i32 %f1, %f2 - ret i32 %final + %f1 = phi i32 [ %l10, %.lr.ph ] + ret i32 %f1 } ; Predicated loop, cannot (yet) use in-loop reductions. -define i32 @reduction_predicated(i32 %n, i32* noalias nocapture %A, i32* noalias nocapture %B) nounwind uwtable readonly noinline ssp { +define i32 @reduction_predicated(i32* noalias nocapture %A, i32* noalias nocapture %B) { ; CHECK-LABEL: @reduction_predicated( -; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[N:%.*]], 0 -; CHECK-NEXT: br i1 [[TMP1]], label [[DOTLR_PH_PREHEADER:%.*]], label [[DOT_CRIT_EDGE:%.*]] -; CHECK: .lr.ph.preheader: -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[N]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP2]] to i64 +; CHECK-NEXT: entry: ; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] ; CHECK: vector.ph: -; CHECK-NEXT: [[N_RND_UP:%.*]] = add nuw nsw i64 [[TMP3]], 4 -; CHECK-NEXT: [[N_VEC:%.*]] = and i64 [[N_RND_UP]], 8589934588 -; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <4 x i64> undef, i64 [[TMP3]], i32 0 -; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT]], <4 x i64> undef, <4 x i32> zeroinitializer ; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] ; CHECK: vector.body: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_LOAD_CONTINUE14:%.*]] ] -; CHECK-NEXT: [[VEC_IND:%.*]] = phi <4 x i64> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT:%.*]], [[PRED_LOAD_CONTINUE14]] ] -; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP50:%.*]], [[PRED_LOAD_CONTINUE14]] ] -; CHECK-NEXT: [[VEC_IND15:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT16:%.*]], [[PRED_LOAD_CONTINUE14]] ] -; CHECK-NEXT: [[TMP4:%.*]] = or i64 [[INDEX]], 1 -; CHECK-NEXT: [[TMP5:%.*]] = or i64 [[INDEX]], 2 -; CHECK-NEXT: [[TMP6:%.*]] = or i64 [[INDEX]], 3 -; CHECK-NEXT: [[TMP7:%.*]] = icmp ule <4 x i64> [[VEC_IND]], [[BROADCAST_SPLAT]] -; CHECK-NEXT: [[TMP8:%.*]] = extractelement <4 x i1> [[TMP7]], i32 0 -; CHECK-NEXT: br i1 [[TMP8]], label [[PRED_LOAD_IF:%.*]], label [[PRED_LOAD_CONTINUE:%.*]] -; CHECK: pred.load.if: -; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 -; CHECK-NEXT: [[TMP11:%.*]] = insertelement <4 x i32> undef, i32 [[TMP10]], i32 0 -; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE]] -; CHECK: pred.load.continue: -; CHECK-NEXT: [[TMP12:%.*]] = phi <4 x i32> [ undef, [[VECTOR_BODY]] ], [ [[TMP11]], [[PRED_LOAD_IF]] ] -; CHECK-NEXT: [[TMP13:%.*]] = extractelement <4 x i1> [[TMP7]], i32 1 -; CHECK-NEXT: br i1 [[TMP13]], label [[PRED_LOAD_IF1:%.*]], label [[PRED_LOAD_CONTINUE2:%.*]] -; CHECK: pred.load.if1: -; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[TMP4]] -; CHECK-NEXT: [[TMP15:%.*]] = load i32, i32* [[TMP14]], align 4 -; CHECK-NEXT: [[TMP16:%.*]] = insertelement <4 x i32> [[TMP12]], i32 [[TMP15]], i32 1 -; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE2]] -; CHECK: pred.load.continue2: -; CHECK-NEXT: [[TMP17:%.*]] = phi <4 x i32> [ [[TMP12]], [[PRED_LOAD_CONTINUE]] ], [ [[TMP16]], [[PRED_LOAD_IF1]] ] -; CHECK-NEXT: [[TMP18:%.*]] = extractelement <4 x i1> [[TMP7]], i32 2 -; CHECK-NEXT: br i1 [[TMP18]], label [[PRED_LOAD_IF3:%.*]], label [[PRED_LOAD_CONTINUE4:%.*]] -; CHECK: pred.load.if3: -; CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[TMP5]] -; CHECK-NEXT: [[TMP20:%.*]] = load i32, i32* [[TMP19]], align 4 -; CHECK-NEXT: [[TMP21:%.*]] = insertelement <4 x i32> [[TMP17]], i32 [[TMP20]], i32 2 -; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE4]] -; CHECK: pred.load.continue4: -; CHECK-NEXT: [[TMP22:%.*]] = phi <4 x i32> [ [[TMP17]], [[PRED_LOAD_CONTINUE2]] ], [ [[TMP21]], [[PRED_LOAD_IF3]] ] -; CHECK-NEXT: [[TMP23:%.*]] = extractelement <4 x i1> [[TMP7]], i32 3 -; CHECK-NEXT: br i1 [[TMP23]], label [[PRED_LOAD_IF5:%.*]], label [[PRED_LOAD_CONTINUE6:%.*]] -; CHECK: pred.load.if5: -; CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds i32, i32* [[A]], i64 [[TMP6]] -; CHECK-NEXT: [[TMP25:%.*]] = load i32, i32* [[TMP24]], align 4 -; CHECK-NEXT: [[TMP26:%.*]] = insertelement <4 x i32> [[TMP22]], i32 [[TMP25]], i32 3 -; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE6]] -; CHECK: pred.load.continue6: -; CHECK-NEXT: [[TMP27:%.*]] = phi <4 x i32> [ [[TMP22]], [[PRED_LOAD_CONTINUE4]] ], [ [[TMP26]], [[PRED_LOAD_IF5]] ] -; CHECK-NEXT: [[TMP28:%.*]] = extractelement <4 x i1> [[TMP7]], i32 0 -; CHECK-NEXT: br i1 [[TMP28]], label [[PRED_LOAD_IF7:%.*]], label [[PRED_LOAD_CONTINUE8:%.*]] -; CHECK: pred.load.if7: -; CHECK-NEXT: [[TMP29:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] -; CHECK-NEXT: [[TMP30:%.*]] = load i32, i32* [[TMP29]], align 4 -; CHECK-NEXT: [[TMP31:%.*]] = insertelement <4 x i32> undef, i32 [[TMP30]], i32 0 -; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE8]] -; CHECK: pred.load.continue8: -; CHECK-NEXT: [[TMP32:%.*]] = phi <4 x i32> [ undef, [[PRED_LOAD_CONTINUE6]] ], [ [[TMP31]], [[PRED_LOAD_IF7]] ] -; CHECK-NEXT: [[TMP33:%.*]] = extractelement <4 x i1> [[TMP7]], i32 1 -; CHECK-NEXT: br i1 [[TMP33]], label [[PRED_LOAD_IF9:%.*]], label [[PRED_LOAD_CONTINUE10:%.*]] -; CHECK: pred.load.if9: -; CHECK-NEXT: [[TMP34:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[TMP4]] -; CHECK-NEXT: [[TMP35:%.*]] = load i32, i32* [[TMP34]], align 4 -; CHECK-NEXT: [[TMP36:%.*]] = insertelement <4 x i32> [[TMP32]], i32 [[TMP35]], i32 1 -; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE10]] -; CHECK: pred.load.continue10: -; CHECK-NEXT: [[TMP37:%.*]] = phi <4 x i32> [ [[TMP32]], [[PRED_LOAD_CONTINUE8]] ], [ [[TMP36]], [[PRED_LOAD_IF9]] ] -; CHECK-NEXT: [[TMP38:%.*]] = extractelement <4 x i1> [[TMP7]], i32 2 -; CHECK-NEXT: br i1 [[TMP38]], label [[PRED_LOAD_IF11:%.*]], label [[PRED_LOAD_CONTINUE12:%.*]] -; CHECK: pred.load.if11: -; CHECK-NEXT: [[TMP39:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[TMP5]] -; CHECK-NEXT: [[TMP40:%.*]] = load i32, i32* [[TMP39]], align 4 -; CHECK-NEXT: [[TMP41:%.*]] = insertelement <4 x i32> [[TMP37]], i32 [[TMP40]], i32 2 -; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE12]] -; CHECK: pred.load.continue12: -; CHECK-NEXT: [[TMP42:%.*]] = phi <4 x i32> [ [[TMP37]], [[PRED_LOAD_CONTINUE10]] ], [ [[TMP41]], [[PRED_LOAD_IF11]] ] -; CHECK-NEXT: [[TMP43:%.*]] = extractelement <4 x i1> [[TMP7]], i32 3 -; CHECK-NEXT: br i1 [[TMP43]], label [[PRED_LOAD_IF13:%.*]], label [[PRED_LOAD_CONTINUE14]] -; CHECK: pred.load.if13: -; CHECK-NEXT: [[TMP44:%.*]] = getelementptr inbounds i32, i32* [[B]], i64 [[TMP6]] -; CHECK-NEXT: [[TMP45:%.*]] = load i32, i32* [[TMP44]], align 4 -; CHECK-NEXT: [[TMP46:%.*]] = insertelement <4 x i32> [[TMP42]], i32 [[TMP45]], i32 3 -; CHECK-NEXT: br label [[PRED_LOAD_CONTINUE14]] -; CHECK: pred.load.continue14: -; CHECK-NEXT: [[TMP47:%.*]] = phi <4 x i32> [ [[TMP42]], [[PRED_LOAD_CONTINUE12]] ], [ [[TMP46]], [[PRED_LOAD_IF13]] ] -; CHECK-NEXT: [[TMP48:%.*]] = add <4 x i32> [[VEC_PHI]], [[VEC_IND15]] -; CHECK-NEXT: [[TMP49:%.*]] = add <4 x i32> [[TMP48]], [[TMP27]] -; CHECK-NEXT: [[TMP50]] = add <4 x i32> [[TMP49]], [[TMP47]] +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ zeroinitializer, [[VECTOR_PH]] ], [ [[TMP6:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_IND2:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[VEC_IND_NEXT3:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[TMP0]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, <4 x i32>* [[TMP1]], align 4 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[B:%.*]], i64 [[INDEX]] +; CHECK-NEXT: [[TMP3:%.*]] = bitcast i32* [[TMP2]] to <4 x i32>* +; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <4 x i32>, <4 x i32>* [[TMP3]], align 4 +; CHECK-NEXT: [[TMP4:%.*]] = add <4 x i32> [[VEC_PHI]], [[VEC_IND2]] +; CHECK-NEXT: [[TMP5:%.*]] = add <4 x i32> [[TMP4]], [[WIDE_LOAD]] +; CHECK-NEXT: [[TMP6]] = add <4 x i32> [[TMP5]], [[WIDE_LOAD1]] ; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4 -; CHECK-NEXT: [[VEC_IND_NEXT]] = add <4 x i64> [[VEC_IND]], -; CHECK-NEXT: [[VEC_IND_NEXT16]] = add <4 x i32> [[VEC_IND15]], -; CHECK-NEXT: [[TMP51:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP51]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !32 +; CHECK-NEXT: [[VEC_IND_NEXT3]] = add <4 x i32> [[VEC_IND2]], +; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !34 ; CHECK: middle.block: -; CHECK-NEXT: [[TMP52:%.*]] = select <4 x i1> [[TMP7]], <4 x i32> [[TMP50]], <4 x i32> [[VEC_PHI]] -; CHECK-NEXT: [[TMP53:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP52]]) -; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE_LOOPEXIT:%.*]], label [[SCALAR_PH]] +; CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.experimental.vector.reduce.add.v4i32(<4 x i32> [[TMP6]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] ; CHECK: scalar.ph: ; CHECK-NEXT: br label [[DOTLR_PH:%.*]] ; CHECK: .lr.ph: -; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE_LOOPEXIT]], label [[DOTLR_PH]], !llvm.loop !33 -; CHECK: ._crit_edge.loopexit: -; CHECK-NEXT: [[DOTLCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP53]], [[MIDDLE_BLOCK]] ] -; CHECK-NEXT: br label [[DOT_CRIT_EDGE]] +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !35 ; CHECK: ._crit_edge: -; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[DOTLCSSA]], [[DOT_CRIT_EDGE_LOOPEXIT]] ] +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP8]], [[MIDDLE_BLOCK]] ] ; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] ; - %1 = icmp sgt i32 %n, 0 - br i1 %1, label %.lr.ph, label %._crit_edge - -.lr.ph: ; preds = %0, %.lr.ph - %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %0 ] - %sum.02 = phi i32 [ %9, %.lr.ph ], [ 0, %0 ] - %2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv - %3 = load i32, i32* %2, align 4 - %4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv - %5 = load i32, i32* %4, align 4 - %6 = trunc i64 %indvars.iv to i32 - %7 = add i32 %sum.02, %6 - %8 = add i32 %7, %3 - %9 = add i32 %8, %5 +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i64 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02 = phi i32 [ %l9, %.lr.ph ], [ 0, %entry ] + %l2 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv + %l3 = load i32, i32* %l2, align 4 + %l4 = getelementptr inbounds i32, i32* %B, i64 %indvars.iv + %l5 = load i32, i32* %l4, align 4 + %l6 = trunc i64 %indvars.iv to i32 + %l7 = add i32 %sum.02, %l6 + %l8 = add i32 %l7, %l3 + %l9 = add i32 %l8, %l5 %indvars.iv.next = add i64 %indvars.iv, 1 %lftr.wideiv = trunc i64 %indvars.iv.next to i32 - %exitcond = icmp eq i32 %lftr.wideiv, %n + %exitcond = icmp eq i32 %lftr.wideiv, 256 br i1 %exitcond, label %._crit_edge, label %.lr.ph, !llvm.loop !6 -._crit_edge: ; preds = %.lr.ph, %0 - %sum.0.lcssa = phi i32 [ 0, %0 ], [ %9, %.lr.ph ] +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l9, %.lr.ph ] ret i32 %sum.0.lcssa } +define i8 @reduction_add_trunc(i8* noalias nocapture %A) { +; CHECK-LABEL: @reduction_add_trunc( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i8> [ , [[VECTOR_PH]] ], [ [[TMP3:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[INDEX]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i64 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <4 x i8>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3]] = add <4 x i8> [[VEC_PHI]], [[WIDE_LOAD]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP4]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !36 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP5:%.*]] = call i8 @llvm.experimental.vector.reduce.add.v4i8(<4 x i8> [[TMP3]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: br label [[DOTLR_PH:%.*]] +; CHECK: .lr.ph: +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !37 +; CHECK: ._crit_edge: +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i8 [ undef, [[DOTLR_PH]] ], [ [[TMP5]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: ret i8 [[SUM_0_LCSSA]] +; +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i32 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02p = phi i32 [ %l9, %.lr.ph ], [ 255, %entry ] + %sum.02 = and i32 %sum.02p, 255 + %l2 = getelementptr inbounds i8, i8* %A, i32 %indvars.iv + %l3 = load i8, i8* %l2, align 4 + %l3e = zext i8 %l3 to i32 + %l9 = add i32 %sum.02, %l3e + %indvars.iv.next = add i32 %indvars.iv, 1 + %exitcond = icmp eq i32 %indvars.iv.next, 256 + br i1 %exitcond, label %._crit_edge, label %.lr.ph + +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l9, %.lr.ph ] + %ret = trunc i32 %sum.0.lcssa to i8 + ret i8 %ret +} + + +define i8 @reduction_and_trunc(i8* noalias nocapture %A) { +; CHECK-LABEL: @reduction_and_trunc( +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] +; CHECK: vector.ph: +; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] +; CHECK: vector.body: +; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[VEC_PHI:%.*]] = phi <4 x i32> [ , [[VECTOR_PH]] ], [ [[TMP4:%.*]], [[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[INDEX]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, i8* [[A:%.*]], i64 [[TMP0]] +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to <4 x i8>* +; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = zext <4 x i8> [[WIDE_LOAD]] to <4 x i32> +; CHECK-NEXT: [[TMP4]] = and <4 x i32> [[VEC_PHI]], [[TMP3]] +; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 4 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[INDEX_NEXT]], 256 +; CHECK-NEXT: br i1 [[TMP5]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !38 +; CHECK: middle.block: +; CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.experimental.vector.reduce.and.v4i32(<4 x i32> [[TMP4]]) +; CHECK-NEXT: br i1 true, label [[DOT_CRIT_EDGE:%.*]], label [[SCALAR_PH]] +; CHECK: scalar.ph: +; CHECK-NEXT: br label [[DOTLR_PH:%.*]] +; CHECK: .lr.ph: +; CHECK-NEXT: br i1 undef, label [[DOT_CRIT_EDGE]], label [[DOTLR_PH]], !llvm.loop !39 +; CHECK: ._crit_edge: +; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ undef, [[DOTLR_PH]] ], [ [[TMP6]], [[MIDDLE_BLOCK]] ] +; CHECK-NEXT: [[RET:%.*]] = trunc i32 [[SUM_0_LCSSA]] to i8 +; CHECK-NEXT: ret i8 [[RET]] +; +entry: + br label %.lr.ph + +.lr.ph: ; preds = %entry, %.lr.ph + %indvars.iv = phi i32 [ %indvars.iv.next, %.lr.ph ], [ 0, %entry ] + %sum.02p = phi i32 [ %l9, %.lr.ph ], [ 255, %entry ] + %sum.02 = and i32 %sum.02p, 255 + %l2 = getelementptr inbounds i8, i8* %A, i32 %indvars.iv + %l3 = load i8, i8* %l2, align 4 + %l3e = zext i8 %l3 to i32 + %l9 = and i32 %sum.02, %l3e + %indvars.iv.next = add i32 %indvars.iv, 1 + %exitcond = icmp eq i32 %indvars.iv.next, 256 + br i1 %exitcond, label %._crit_edge, label %.lr.ph + +._crit_edge: ; preds = %.lr.ph + %sum.0.lcssa = phi i32 [ %l9, %.lr.ph ] + %ret = trunc i32 %sum.0.lcssa to i8 + ret i8 %ret +} + !6 = distinct !{!6, !7, !8} !7 = !{!"llvm.loop.vectorize.predicate.enable", i1 true} !8 = !{!"llvm.loop.vectorize.enable", i1 true} From 918f3fc2c7cf8116b04bfc00125af53214671fc6 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 18 Jul 2020 10:08:17 -0400 Subject: [PATCH 714/771] AMDGPU/GlobalISel: Fix test copy paste error --- .../AMDGPU/GlobalISel/legalize-fmaxnum.mir | 322 +++++++++--------- 1 file changed, 161 insertions(+), 161 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fmaxnum.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fmaxnum.mir index f6456cd57f01e..8b9b0e972e6f4 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fmaxnum.mir +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-fmaxnum.mir @@ -4,7 +4,7 @@ # RUN: llc -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -run-pass=legalizer %s -o - | FileCheck -check-prefix=GFX9 %s --- -name: test_fminnum_s32_ieee_mode_on +name: test_fmaxnum_s32_ieee_mode_on machineFunctionInfo: mode: ieee: true @@ -12,35 +12,35 @@ body: | bb.0: liveins: $vgpr0, $vgpr1 - ; SI-LABEL: name: test_fminnum_s32_ieee_mode_on + ; SI-LABEL: name: test_fmaxnum_s32_ieee_mode_on ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; SI: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY]] ; SI: [[FCANONICALIZE1:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY1]] - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; SI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; VI-LABEL: name: test_fminnum_s32_ieee_mode_on + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; SI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; VI-LABEL: name: test_fmaxnum_s32_ieee_mode_on ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY]] ; VI: [[FCANONICALIZE1:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY1]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; VI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; GFX9-LABEL: name: test_fminnum_s32_ieee_mode_on + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; VI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; GFX9-LABEL: name: test_fmaxnum_s32_ieee_mode_on ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY]] ; GFX9: [[FCANONICALIZE1:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY1]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; GFX9: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; GFX9: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 - %2:_(s32) = G_FMINNUM %0, %1 + %2:_(s32) = G_FMAXNUM %0, %1 $vgpr0 = COPY %2 ... --- -name: test_fminnum_s32_ieee_mode_off +name: test_fmaxnum_s32_ieee_mode_off machineFunctionInfo: mode: ieee: false @@ -48,280 +48,280 @@ body: | bb.0: liveins: $vgpr0, $vgpr1 - ; SI-LABEL: name: test_fminnum_s32_ieee_mode_off + ; SI-LABEL: name: test_fmaxnum_s32_ieee_mode_off ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 - ; SI: [[FMINNUM:%[0-9]+]]:_(s32) = G_FMINNUM [[COPY]], [[COPY1]] - ; SI: $vgpr0 = COPY [[FMINNUM]](s32) - ; VI-LABEL: name: test_fminnum_s32_ieee_mode_off + ; SI: [[FMAXNUM:%[0-9]+]]:_(s32) = G_FMAXNUM [[COPY]], [[COPY1]] + ; SI: $vgpr0 = COPY [[FMAXNUM]](s32) + ; VI-LABEL: name: test_fmaxnum_s32_ieee_mode_off ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 - ; VI: [[FMINNUM:%[0-9]+]]:_(s32) = G_FMINNUM [[COPY]], [[COPY1]] - ; VI: $vgpr0 = COPY [[FMINNUM]](s32) - ; GFX9-LABEL: name: test_fminnum_s32_ieee_mode_off + ; VI: [[FMAXNUM:%[0-9]+]]:_(s32) = G_FMAXNUM [[COPY]], [[COPY1]] + ; VI: $vgpr0 = COPY [[FMAXNUM]](s32) + ; GFX9-LABEL: name: test_fmaxnum_s32_ieee_mode_off ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 - ; GFX9: [[FMINNUM:%[0-9]+]]:_(s32) = G_FMINNUM [[COPY]], [[COPY1]] - ; GFX9: $vgpr0 = COPY [[FMINNUM]](s32) + ; GFX9: [[FMAXNUM:%[0-9]+]]:_(s32) = G_FMAXNUM [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[FMAXNUM]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 - %2:_(s32) = G_FMINNUM %0, %1 + %2:_(s32) = G_FMAXNUM %0, %1 $vgpr0 = COPY %2 ... --- -name: test_fminnum_s32_nnan +name: test_fmaxnum_s32_nnan body: | bb.0: liveins: $vgpr0, $vgpr1 - ; SI-LABEL: name: test_fminnum_s32_nnan + ; SI-LABEL: name: test_fmaxnum_s32_nnan ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = nnan G_FMINNUM_IEEE [[COPY]], [[COPY1]] - ; SI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; VI-LABEL: name: test_fminnum_s32_nnan + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = nnan G_FMAXNUM_IEEE [[COPY]], [[COPY1]] + ; SI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; VI-LABEL: name: test_fmaxnum_s32_nnan ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = nnan G_FMINNUM_IEEE [[COPY]], [[COPY1]] - ; VI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; GFX9-LABEL: name: test_fminnum_s32_nnan + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = nnan G_FMAXNUM_IEEE [[COPY]], [[COPY1]] + ; VI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; GFX9-LABEL: name: test_fmaxnum_s32_nnan ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = nnan G_FMINNUM_IEEE [[COPY]], [[COPY1]] - ; GFX9: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = nnan G_FMAXNUM_IEEE [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 - %2:_(s32) = nnan G_FMINNUM %0, %1 + %2:_(s32) = nnan G_FMAXNUM %0, %1 $vgpr0 = COPY %2 ... --- -name: test_fminnum_s32_nnan_lhs +name: test_fmaxnum_s32_nnan_lhs body: | bb.0: liveins: $vgpr0, $vgpr1 - ; SI-LABEL: name: test_fminnum_s32_nnan_lhs + ; SI-LABEL: name: test_fmaxnum_s32_nnan_lhs ; SI: [[COPY:%[0-9]+]]:_(s32) = nnan COPY $vgpr0 ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; SI: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY1]] - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[COPY]], [[FCANONICALIZE]] - ; SI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; VI-LABEL: name: test_fminnum_s32_nnan_lhs + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[COPY]], [[FCANONICALIZE]] + ; SI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; VI-LABEL: name: test_fmaxnum_s32_nnan_lhs ; VI: [[COPY:%[0-9]+]]:_(s32) = nnan COPY $vgpr0 ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY1]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[COPY]], [[FCANONICALIZE]] - ; VI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; GFX9-LABEL: name: test_fminnum_s32_nnan_lhs + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[COPY]], [[FCANONICALIZE]] + ; VI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; GFX9-LABEL: name: test_fmaxnum_s32_nnan_lhs ; GFX9: [[COPY:%[0-9]+]]:_(s32) = nnan COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY1]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[COPY]], [[FCANONICALIZE]] - ; GFX9: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[COPY]], [[FCANONICALIZE]] + ; GFX9: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) %0:_(s32) = nnan COPY $vgpr0 %1:_(s32) = COPY $vgpr1 - %2:_(s32) = G_FMINNUM %0, %1 + %2:_(s32) = G_FMAXNUM %0, %1 $vgpr0 = COPY %2 ... --- -name: test_fminnum_s32_nnan_rhs +name: test_fmaxnum_s32_nnan_rhs body: | bb.0: liveins: $vgpr0, $vgpr1 - ; SI-LABEL: name: test_fminnum_s32_nnan_rhs + ; SI-LABEL: name: test_fmaxnum_s32_nnan_rhs ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; SI: [[COPY1:%[0-9]+]]:_(s32) = nnan COPY $vgpr1 ; SI: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY]] - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[COPY1]] - ; SI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; VI-LABEL: name: test_fminnum_s32_nnan_rhs + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[COPY1]] + ; SI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; VI-LABEL: name: test_fmaxnum_s32_nnan_rhs ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; VI: [[COPY1:%[0-9]+]]:_(s32) = nnan COPY $vgpr1 ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[COPY1]] - ; VI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; GFX9-LABEL: name: test_fminnum_s32_nnan_rhs + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[COPY1]] + ; VI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; GFX9-LABEL: name: test_fmaxnum_s32_nnan_rhs ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = nnan COPY $vgpr1 ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[COPY]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[COPY1]] - ; GFX9: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = nnan COPY $vgpr1 - %2:_(s32) = G_FMINNUM %0, %1 + %2:_(s32) = G_FMAXNUM %0, %1 $vgpr0 = COPY %2 ... --- -name: test_fminnum_s32_nnan_lhs_rhs +name: test_fmaxnum_s32_nnan_lhs_rhs body: | bb.0: liveins: $vgpr0, $vgpr1 - ; SI-LABEL: name: test_fminnum_s32_nnan_lhs_rhs + ; SI-LABEL: name: test_fmaxnum_s32_nnan_lhs_rhs ; SI: [[COPY:%[0-9]+]]:_(s32) = nnan COPY $vgpr0 ; SI: [[COPY1:%[0-9]+]]:_(s32) = nnan COPY $vgpr1 - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[COPY]], [[COPY1]] - ; SI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; VI-LABEL: name: test_fminnum_s32_nnan_lhs_rhs + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[COPY]], [[COPY1]] + ; SI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; VI-LABEL: name: test_fmaxnum_s32_nnan_lhs_rhs ; VI: [[COPY:%[0-9]+]]:_(s32) = nnan COPY $vgpr0 ; VI: [[COPY1:%[0-9]+]]:_(s32) = nnan COPY $vgpr1 - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[COPY]], [[COPY1]] - ; VI: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) - ; GFX9-LABEL: name: test_fminnum_s32_nnan_lhs_rhs + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[COPY]], [[COPY1]] + ; VI: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) + ; GFX9-LABEL: name: test_fmaxnum_s32_nnan_lhs_rhs ; GFX9: [[COPY:%[0-9]+]]:_(s32) = nnan COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = nnan COPY $vgpr1 - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[COPY]], [[COPY1]] - ; GFX9: $vgpr0 = COPY [[FMINNUM_IEEE]](s32) + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[COPY]], [[COPY1]] + ; GFX9: $vgpr0 = COPY [[FMAXNUM_IEEE]](s32) %0:_(s32) = nnan COPY $vgpr0 %1:_(s32) = nnan COPY $vgpr1 - %2:_(s32) = G_FMINNUM %0, %1 + %2:_(s32) = G_FMAXNUM %0, %1 $vgpr0 = COPY %2 ... --- -name: test_fminnum_s64 +name: test_fmaxnum_s64 body: | bb.0: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 - ; SI-LABEL: name: test_fminnum_s64 + ; SI-LABEL: name: test_fmaxnum_s64 ; SI: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 ; SI: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 ; SI: [[FCANONICALIZE:%[0-9]+]]:_(s64) = G_FCANONICALIZE [[COPY]] ; SI: [[FCANONICALIZE1:%[0-9]+]]:_(s64) = G_FCANONICALIZE [[COPY1]] - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s64) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; SI: $vgpr0_vgpr1 = COPY [[FMINNUM_IEEE]](s64) - ; VI-LABEL: name: test_fminnum_s64 + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s64) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; SI: $vgpr0_vgpr1 = COPY [[FMAXNUM_IEEE]](s64) + ; VI-LABEL: name: test_fmaxnum_s64 ; VI: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 ; VI: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s64) = G_FCANONICALIZE [[COPY]] ; VI: [[FCANONICALIZE1:%[0-9]+]]:_(s64) = G_FCANONICALIZE [[COPY1]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s64) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; VI: $vgpr0_vgpr1 = COPY [[FMINNUM_IEEE]](s64) - ; GFX9-LABEL: name: test_fminnum_s64 + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s64) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; VI: $vgpr0_vgpr1 = COPY [[FMAXNUM_IEEE]](s64) + ; GFX9-LABEL: name: test_fmaxnum_s64 ; GFX9: [[COPY:%[0-9]+]]:_(s64) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(s64) = COPY $vgpr2_vgpr3 ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(s64) = G_FCANONICALIZE [[COPY]] ; GFX9: [[FCANONICALIZE1:%[0-9]+]]:_(s64) = G_FCANONICALIZE [[COPY1]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(s64) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; GFX9: $vgpr0_vgpr1 = COPY [[FMINNUM_IEEE]](s64) + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(s64) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; GFX9: $vgpr0_vgpr1 = COPY [[FMAXNUM_IEEE]](s64) %0:_(s64) = COPY $vgpr0_vgpr1 %1:_(s64) = COPY $vgpr2_vgpr3 - %2:_(s64) = G_FMINNUM %0, %1 + %2:_(s64) = G_FMAXNUM %0, %1 $vgpr0_vgpr1 = COPY %2 ... --- -name: test_fminnum_s16 +name: test_fmaxnum_s16 body: | bb.0: liveins: $vgpr0, $vgpr1 - ; SI-LABEL: name: test_fminnum_s16 + ; SI-LABEL: name: test_fmaxnum_s16 ; SI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; SI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; SI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) ; SI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; SI: [[FPEXT:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC]](s16) ; SI: [[FPEXT1:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC1]](s16) - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT]], [[FPEXT1]] - ; SI: [[FPTRUNC:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE]](s32) + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT]], [[FPEXT1]] + ; SI: [[FPTRUNC:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE]](s32) ; SI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FPTRUNC]](s16) ; SI: $vgpr0 = COPY [[ANYEXT]](s32) - ; VI-LABEL: name: test_fminnum_s16 + ; VI-LABEL: name: test_fmaxnum_s16 ; VI: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; VI: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; VI: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) ; VI: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC]] ; VI: [[FCANONICALIZE1:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC1]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMINNUM_IEEE]](s16) + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; VI: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMAXNUM_IEEE]](s16) ; VI: $vgpr0 = COPY [[ANYEXT]](s32) - ; GFX9-LABEL: name: test_fminnum_s16 + ; GFX9-LABEL: name: test_fmaxnum_s16 ; GFX9: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1 ; GFX9: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[COPY]](s32) ; GFX9: [[TRUNC1:%[0-9]+]]:_(s16) = G_TRUNC [[COPY1]](s32) ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC]] ; GFX9: [[FCANONICALIZE1:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC1]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMINNUM_IEEE]](s16) + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; GFX9: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[FMAXNUM_IEEE]](s16) ; GFX9: $vgpr0 = COPY [[ANYEXT]](s32) %0:_(s32) = COPY $vgpr0 %1:_(s32) = COPY $vgpr1 %2:_(s16) = G_TRUNC %0 %3:_(s16) = G_TRUNC %1 - %4:_(s16) = G_FMINNUM %2, %3 + %4:_(s16) = G_FMAXNUM %2, %3 %5:_(s32) = G_ANYEXT %4 $vgpr0 = COPY %5 ... --- -name: test_fminnum_v2s32 +name: test_fmaxnum_v2s32 body: | bb.0: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 - ; SI-LABEL: name: test_fminnum_v2s32 + ; SI-LABEL: name: test_fmaxnum_v2s32 ; SI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; SI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 ; SI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) ; SI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) ; SI: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV]] ; SI: [[FCANONICALIZE1:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV2]] - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] ; SI: [[FCANONICALIZE2:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV1]] ; SI: [[FCANONICALIZE3:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV3]] - ; SI: [[FMINNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] - ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FMINNUM_IEEE]](s32), [[FMINNUM_IEEE1]](s32) + ; SI: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] + ; SI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FMAXNUM_IEEE]](s32), [[FMAXNUM_IEEE1]](s32) ; SI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) - ; VI-LABEL: name: test_fminnum_v2s32 + ; VI-LABEL: name: test_fmaxnum_v2s32 ; VI: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; VI: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 ; VI: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) ; VI: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV]] ; VI: [[FCANONICALIZE1:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV2]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] ; VI: [[FCANONICALIZE2:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV1]] ; VI: [[FCANONICALIZE3:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV3]] - ; VI: [[FMINNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] - ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FMINNUM_IEEE]](s32), [[FMINNUM_IEEE1]](s32) + ; VI: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] + ; VI: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FMAXNUM_IEEE]](s32), [[FMAXNUM_IEEE1]](s32) ; VI: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) - ; GFX9-LABEL: name: test_fminnum_v2s32 + ; GFX9-LABEL: name: test_fmaxnum_v2s32 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s32>) = COPY $vgpr2_vgpr3 ; GFX9: [[UV:%[0-9]+]]:_(s32), [[UV1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY]](<2 x s32>) ; GFX9: [[UV2:%[0-9]+]]:_(s32), [[UV3:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[COPY1]](<2 x s32>) ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV]] ; GFX9: [[FCANONICALIZE1:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV2]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] ; GFX9: [[FCANONICALIZE2:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV1]] ; GFX9: [[FCANONICALIZE3:%[0-9]+]]:_(s32) = G_FCANONICALIZE [[UV3]] - ; GFX9: [[FMINNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] - ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FMINNUM_IEEE]](s32), [[FMINNUM_IEEE1]](s32) + ; GFX9: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] + ; GFX9: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x s32>) = G_BUILD_VECTOR [[FMAXNUM_IEEE]](s32), [[FMAXNUM_IEEE1]](s32) ; GFX9: $vgpr0_vgpr1 = COPY [[BUILD_VECTOR]](<2 x s32>) %0:_(<2 x s32>) = COPY $vgpr0_vgpr1 %1:_(<2 x s32>) = COPY $vgpr2_vgpr3 - %2:_(<2 x s32>) = G_FMINNUM %0, %1 + %2:_(<2 x s32>) = G_FMAXNUM %0, %1 $vgpr0_vgpr1 = COPY %2 ... --- -name: test_fminnum_v2s16 +name: test_fmaxnum_v2s16 body: | bb.0: liveins: $vgpr0, $vgpr1 - ; SI-LABEL: name: test_fminnum_v2s16 + ; SI-LABEL: name: test_fmaxnum_v2s16 ; SI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; SI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 ; SI: [[BITCAST:%[0-9]+]]:_(s32) = G_BITCAST [[COPY]](<2 x s16>) @@ -335,19 +335,19 @@ body: | ; SI: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR1]](s32) ; SI: [[FPEXT:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC]](s16) ; SI: [[FPEXT1:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC2]](s16) - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT]], [[FPEXT1]] - ; SI: [[FPTRUNC:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE]](s32) + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT]], [[FPEXT1]] + ; SI: [[FPTRUNC:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE]](s32) ; SI: [[FPEXT2:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC1]](s16) ; SI: [[FPEXT3:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC3]](s16) - ; SI: [[FMINNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT2]], [[FPEXT3]] - ; SI: [[FPTRUNC1:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE1]](s32) + ; SI: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT2]], [[FPEXT3]] + ; SI: [[FPTRUNC1:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE1]](s32) ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FPTRUNC]](s16) ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FPTRUNC1]](s16) ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT1]], [[C]](s32) ; SI: [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT]], [[SHL]] ; SI: [[BITCAST2:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[OR]](s32) ; SI: $vgpr0 = COPY [[BITCAST2]](<2 x s16>) - ; VI-LABEL: name: test_fminnum_v2s16 + ; VI-LABEL: name: test_fmaxnum_v2s16 ; VI: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; VI: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 ; VI: [[BITCAST:%[0-9]+]]:_(s32) = G_BITCAST [[COPY]](<2 x s16>) @@ -361,36 +361,36 @@ body: | ; VI: [[TRUNC3:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR1]](s32) ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC]] ; VI: [[FCANONICALIZE1:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC2]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] ; VI: [[FCANONICALIZE2:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC1]] ; VI: [[FCANONICALIZE3:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC3]] - ; VI: [[FMINNUM_IEEE1:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] - ; VI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE]](s16) - ; VI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE1]](s16) + ; VI: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] + ; VI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE]](s16) + ; VI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE1]](s16) ; VI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT1]], [[C]](s32) ; VI: [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT]], [[SHL]] ; VI: [[BITCAST2:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[OR]](s32) ; VI: $vgpr0 = COPY [[BITCAST2]](<2 x s16>) - ; GFX9-LABEL: name: test_fminnum_v2s16 + ; GFX9-LABEL: name: test_fmaxnum_v2s16 ; GFX9: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr0 ; GFX9: [[COPY1:%[0-9]+]]:_(<2 x s16>) = COPY $vgpr1 ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[COPY]] ; GFX9: [[FCANONICALIZE1:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[COPY1]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(<2 x s16>) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] - ; GFX9: $vgpr0 = COPY [[FMINNUM_IEEE]](<2 x s16>) + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(<2 x s16>) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; GFX9: $vgpr0 = COPY [[FMAXNUM_IEEE]](<2 x s16>) %0:_(<2 x s16>) = COPY $vgpr0 %1:_(<2 x s16>) = COPY $vgpr1 - %2:_(<2 x s16>) = G_FMINNUM %0, %1 + %2:_(<2 x s16>) = G_FMAXNUM %0, %1 $vgpr0 = COPY %2 ... --- -name: test_fminnum_v3s16 +name: test_fmaxnum_v3s16 body: | bb.0: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 - ; SI-LABEL: name: test_fminnum_v3s16 + ; SI-LABEL: name: test_fmaxnum_v3s16 ; SI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; SI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 ; SI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[COPY]](<4 x s16>), 0 @@ -417,16 +417,16 @@ body: | ; SI: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[BITCAST3]], [[C]](s32) ; SI: [[FPEXT:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC]](s16) ; SI: [[FPEXT1:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC3]](s16) - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT]], [[FPEXT1]] - ; SI: [[FPTRUNC:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE]](s32) + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT]], [[FPEXT1]] + ; SI: [[FPTRUNC:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE]](s32) ; SI: [[FPEXT2:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC1]](s16) ; SI: [[FPEXT3:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC4]](s16) - ; SI: [[FMINNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT2]], [[FPEXT3]] - ; SI: [[FPTRUNC1:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE1]](s32) + ; SI: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT2]], [[FPEXT3]] + ; SI: [[FPTRUNC1:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE1]](s32) ; SI: [[FPEXT4:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC2]](s16) ; SI: [[FPEXT5:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC5]](s16) - ; SI: [[FMINNUM_IEEE2:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT4]], [[FPEXT5]] - ; SI: [[FPTRUNC2:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE2]](s32) + ; SI: [[FMAXNUM_IEEE2:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT4]], [[FPEXT5]] + ; SI: [[FPTRUNC2:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE2]](s32) ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FPTRUNC]](s16) ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FPTRUNC1]](s16) ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT1]], [[C]](s32) @@ -441,7 +441,7 @@ body: | ; SI: [[EXTRACT2:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[CONCAT_VECTORS]](<4 x s16>), 0 ; SI: [[INSERT2:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF]], [[EXTRACT2]](<3 x s16>), 0 ; SI: $vgpr0_vgpr1 = COPY [[INSERT2]](<4 x s16>) - ; VI-LABEL: name: test_fminnum_v3s16 + ; VI-LABEL: name: test_fmaxnum_v3s16 ; VI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; VI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 ; VI: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[COPY]](<4 x s16>), 0 @@ -468,19 +468,19 @@ body: | ; VI: [[LSHR3:%[0-9]+]]:_(s32) = G_LSHR [[BITCAST3]], [[C]](s32) ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC]] ; VI: [[FCANONICALIZE1:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC3]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] ; VI: [[FCANONICALIZE2:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC1]] ; VI: [[FCANONICALIZE3:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC4]] - ; VI: [[FMINNUM_IEEE1:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] + ; VI: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] ; VI: [[FCANONICALIZE4:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC2]] ; VI: [[FCANONICALIZE5:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC5]] - ; VI: [[FMINNUM_IEEE2:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE4]], [[FCANONICALIZE5]] - ; VI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE]](s16) - ; VI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE1]](s16) + ; VI: [[FMAXNUM_IEEE2:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE4]], [[FCANONICALIZE5]] + ; VI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE]](s16) + ; VI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE1]](s16) ; VI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT1]], [[C]](s32) ; VI: [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT]], [[SHL]] ; VI: [[BITCAST4:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[OR]](s32) - ; VI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE2]](s16) + ; VI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE2]](s16) ; VI: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0 ; VI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[C1]], [[C]](s32) ; VI: [[OR1:%[0-9]+]]:_(s32) = G_OR [[ZEXT2]], [[SHL1]] @@ -489,7 +489,7 @@ body: | ; VI: [[EXTRACT2:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[CONCAT_VECTORS]](<4 x s16>), 0 ; VI: [[INSERT2:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF]], [[EXTRACT2]](<3 x s16>), 0 ; VI: $vgpr0_vgpr1 = COPY [[INSERT2]](<4 x s16>) - ; GFX9-LABEL: name: test_fminnum_v3s16 + ; GFX9-LABEL: name: test_fmaxnum_v3s16 ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 ; GFX9: [[EXTRACT:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[COPY]](<4 x s16>), 0 @@ -501,11 +501,11 @@ body: | ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[INSERT1]](<4 x s16>) ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[UV]] ; GFX9: [[FCANONICALIZE1:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[UV2]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(<2 x s16>) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(<2 x s16>) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] ; GFX9: [[FCANONICALIZE2:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[UV1]] ; GFX9: [[FCANONICALIZE3:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[UV3]] - ; GFX9: [[FMINNUM_IEEE1:%[0-9]+]]:_(<2 x s16>) = G_FMINNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] - ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[FMINNUM_IEEE]](<2 x s16>), [[FMINNUM_IEEE1]](<2 x s16>) + ; GFX9: [[FMAXNUM_IEEE1:%[0-9]+]]:_(<2 x s16>) = G_FMAXNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[FMAXNUM_IEEE]](<2 x s16>), [[FMAXNUM_IEEE1]](<2 x s16>) ; GFX9: [[EXTRACT2:%[0-9]+]]:_(<3 x s16>) = G_EXTRACT [[CONCAT_VECTORS]](<4 x s16>), 0 ; GFX9: [[INSERT2:%[0-9]+]]:_(<4 x s16>) = G_INSERT [[DEF]], [[EXTRACT2]](<3 x s16>), 0 ; GFX9: $vgpr0_vgpr1 = COPY [[INSERT2]](<4 x s16>) @@ -513,19 +513,19 @@ body: | %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 %2:_(<3 x s16>) = G_EXTRACT %0, 0 %3:_(<3 x s16>) = G_EXTRACT %1, 0 - %4:_(<3 x s16>) = G_FMINNUM %2, %3 + %4:_(<3 x s16>) = G_FMAXNUM %2, %3 %5:_(<4 x s16>) = G_IMPLICIT_DEF %6:_(<4 x s16>) = G_INSERT %5, %4, 0 $vgpr0_vgpr1 = COPY %6 ... --- -name: test_fminnum_v4s16 +name: test_fmaxnum_v4s16 body: | bb.0: liveins: $vgpr0_vgpr1, $vgpr2_vgpr3 - ; SI-LABEL: name: test_fminnum_v4s16 + ; SI-LABEL: name: test_fmaxnum_v4s16 ; SI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; SI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 ; SI: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) @@ -549,20 +549,20 @@ body: | ; SI: [[TRUNC7:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR3]](s32) ; SI: [[FPEXT:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC]](s16) ; SI: [[FPEXT1:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC4]](s16) - ; SI: [[FMINNUM_IEEE:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT]], [[FPEXT1]] - ; SI: [[FPTRUNC:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE]](s32) + ; SI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT]], [[FPEXT1]] + ; SI: [[FPTRUNC:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE]](s32) ; SI: [[FPEXT2:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC1]](s16) ; SI: [[FPEXT3:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC5]](s16) - ; SI: [[FMINNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT2]], [[FPEXT3]] - ; SI: [[FPTRUNC1:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE1]](s32) + ; SI: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT2]], [[FPEXT3]] + ; SI: [[FPTRUNC1:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE1]](s32) ; SI: [[FPEXT4:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC2]](s16) ; SI: [[FPEXT5:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC6]](s16) - ; SI: [[FMINNUM_IEEE2:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT4]], [[FPEXT5]] - ; SI: [[FPTRUNC2:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE2]](s32) + ; SI: [[FMAXNUM_IEEE2:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT4]], [[FPEXT5]] + ; SI: [[FPTRUNC2:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE2]](s32) ; SI: [[FPEXT6:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC3]](s16) ; SI: [[FPEXT7:%[0-9]+]]:_(s32) = G_FPEXT [[TRUNC7]](s16) - ; SI: [[FMINNUM_IEEE3:%[0-9]+]]:_(s32) = G_FMINNUM_IEEE [[FPEXT6]], [[FPEXT7]] - ; SI: [[FPTRUNC3:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMINNUM_IEEE3]](s32) + ; SI: [[FMAXNUM_IEEE3:%[0-9]+]]:_(s32) = G_FMAXNUM_IEEE [[FPEXT6]], [[FPEXT7]] + ; SI: [[FPTRUNC3:%[0-9]+]]:_(s16) = G_FPTRUNC [[FMAXNUM_IEEE3]](s32) ; SI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FPTRUNC]](s16) ; SI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FPTRUNC1]](s16) ; SI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT1]], [[C]](s32) @@ -575,7 +575,7 @@ body: | ; SI: [[BITCAST5:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[OR1]](s32) ; SI: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[BITCAST4]](<2 x s16>), [[BITCAST5]](<2 x s16>) ; SI: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) - ; VI-LABEL: name: test_fminnum_v4s16 + ; VI-LABEL: name: test_fmaxnum_v4s16 ; VI: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; VI: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 ; VI: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) @@ -599,43 +599,43 @@ body: | ; VI: [[TRUNC7:%[0-9]+]]:_(s16) = G_TRUNC [[LSHR3]](s32) ; VI: [[FCANONICALIZE:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC]] ; VI: [[FCANONICALIZE1:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC4]] - ; VI: [[FMINNUM_IEEE:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; VI: [[FMAXNUM_IEEE:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] ; VI: [[FCANONICALIZE2:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC1]] ; VI: [[FCANONICALIZE3:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC5]] - ; VI: [[FMINNUM_IEEE1:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] + ; VI: [[FMAXNUM_IEEE1:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] ; VI: [[FCANONICALIZE4:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC2]] ; VI: [[FCANONICALIZE5:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC6]] - ; VI: [[FMINNUM_IEEE2:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE4]], [[FCANONICALIZE5]] + ; VI: [[FMAXNUM_IEEE2:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE4]], [[FCANONICALIZE5]] ; VI: [[FCANONICALIZE6:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC3]] ; VI: [[FCANONICALIZE7:%[0-9]+]]:_(s16) = G_FCANONICALIZE [[TRUNC7]] - ; VI: [[FMINNUM_IEEE3:%[0-9]+]]:_(s16) = G_FMINNUM_IEEE [[FCANONICALIZE6]], [[FCANONICALIZE7]] - ; VI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE]](s16) - ; VI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE1]](s16) + ; VI: [[FMAXNUM_IEEE3:%[0-9]+]]:_(s16) = G_FMAXNUM_IEEE [[FCANONICALIZE6]], [[FCANONICALIZE7]] + ; VI: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE]](s16) + ; VI: [[ZEXT1:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE1]](s16) ; VI: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ZEXT1]], [[C]](s32) ; VI: [[OR:%[0-9]+]]:_(s32) = G_OR [[ZEXT]], [[SHL]] ; VI: [[BITCAST4:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[OR]](s32) - ; VI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE2]](s16) - ; VI: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[FMINNUM_IEEE3]](s16) + ; VI: [[ZEXT2:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE2]](s16) + ; VI: [[ZEXT3:%[0-9]+]]:_(s32) = G_ZEXT [[FMAXNUM_IEEE3]](s16) ; VI: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[ZEXT3]], [[C]](s32) ; VI: [[OR1:%[0-9]+]]:_(s32) = G_OR [[ZEXT2]], [[SHL1]] ; VI: [[BITCAST5:%[0-9]+]]:_(<2 x s16>) = G_BITCAST [[OR1]](s32) ; VI: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[BITCAST4]](<2 x s16>), [[BITCAST5]](<2 x s16>) ; VI: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) - ; GFX9-LABEL: name: test_fminnum_v4s16 + ; GFX9-LABEL: name: test_fmaxnum_v4s16 ; GFX9: [[COPY:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr0_vgpr1 ; GFX9: [[COPY1:%[0-9]+]]:_(<4 x s16>) = COPY $vgpr2_vgpr3 ; GFX9: [[UV:%[0-9]+]]:_(<2 x s16>), [[UV1:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY]](<4 x s16>) ; GFX9: [[UV2:%[0-9]+]]:_(<2 x s16>), [[UV3:%[0-9]+]]:_(<2 x s16>) = G_UNMERGE_VALUES [[COPY1]](<4 x s16>) ; GFX9: [[FCANONICALIZE:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[UV]] ; GFX9: [[FCANONICALIZE1:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[UV2]] - ; GFX9: [[FMINNUM_IEEE:%[0-9]+]]:_(<2 x s16>) = G_FMINNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] + ; GFX9: [[FMAXNUM_IEEE:%[0-9]+]]:_(<2 x s16>) = G_FMAXNUM_IEEE [[FCANONICALIZE]], [[FCANONICALIZE1]] ; GFX9: [[FCANONICALIZE2:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[UV1]] ; GFX9: [[FCANONICALIZE3:%[0-9]+]]:_(<2 x s16>) = G_FCANONICALIZE [[UV3]] - ; GFX9: [[FMINNUM_IEEE1:%[0-9]+]]:_(<2 x s16>) = G_FMINNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] - ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[FMINNUM_IEEE]](<2 x s16>), [[FMINNUM_IEEE1]](<2 x s16>) + ; GFX9: [[FMAXNUM_IEEE1:%[0-9]+]]:_(<2 x s16>) = G_FMAXNUM_IEEE [[FCANONICALIZE2]], [[FCANONICALIZE3]] + ; GFX9: [[CONCAT_VECTORS:%[0-9]+]]:_(<4 x s16>) = G_CONCAT_VECTORS [[FMAXNUM_IEEE]](<2 x s16>), [[FMAXNUM_IEEE1]](<2 x s16>) ; GFX9: $vgpr0_vgpr1 = COPY [[CONCAT_VECTORS]](<4 x s16>) %0:_(<4 x s16>) = COPY $vgpr0_vgpr1 %1:_(<4 x s16>) = COPY $vgpr2_vgpr3 - %2:_(<4 x s16>) = G_FMINNUM %0, %1 + %2:_(<4 x s16>) = G_FMAXNUM %0, %1 $vgpr0_vgpr1 = COPY %2 ... From c73df5696696327a15af2f05b30923cd66361ddc Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Sat, 18 Jul 2020 10:35:40 -0400 Subject: [PATCH 715/771] AMDGPU/GlobalISel: Address some test fixmes that don't fail now --- .../GlobalISel/constant-bus-restriction.ll | 505 ++++++------------ .../GlobalISel/llvm.amdgcn.ds.ordered.add.ll | 3 +- .../GlobalISel/llvm.amdgcn.ds.ordered.swap.ll | 3 +- .../AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll | 50 +- llvm/test/CodeGen/AMDGPU/GlobalISel/xnor.ll | 140 ++++- 5 files changed, 341 insertions(+), 360 deletions(-) diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/constant-bus-restriction.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/constant-bus-restriction.ll index ff0de0d1f6090..c815220ef97d9 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/constant-bus-restriction.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/constant-bus-restriction.ll @@ -1,294 +1,182 @@ -; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py -; RUN: llc -global-isel -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -stop-after=regbankselect -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefix=GFX9 %s -; RUN: llc -global-isel -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx1010 -stop-after=regbankselect -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefix=GFX10 %s +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -global-isel -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx900 -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefix=GFX9 %s +; RUN: llc -global-isel -mtriple=amdgcn-mesa-mesa3d -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -enable-var-scope -check-prefix=GFX10 %s ; Make sure we don't violate the constant bus restriction -; FIXME: Make this test isa output when div.fmas works. - define amdgpu_ps float @fmul_s_s(float inreg %src0, float inreg %src1) { - ; GFX9-LABEL: name: fmul_s_s - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[FMUL:%[0-9]+]]:vgpr(s32) = G_FMUL [[COPY2]], [[COPY3]] - ; GFX9: $vgpr0 = COPY [[FMUL]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: fmul_s_s - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[FMUL:%[0-9]+]]:vgpr(s32) = G_FMUL [[COPY2]], [[COPY3]] - ; GFX10: $vgpr0 = COPY [[FMUL]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: fmul_s_s: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_mul_f32_e32 v0, s2, v0 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: fmul_s_s: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_mul_f32_e64 v0, s2, s3 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %result = fmul float %src0, %src1 ret float %result } define amdgpu_ps float @fmul_ss(float inreg %src) { - ; GFX9-LABEL: name: fmul_ss - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[FMUL:%[0-9]+]]:vgpr(s32) = G_FMUL [[COPY1]], [[COPY2]] - ; GFX9: $vgpr0 = COPY [[FMUL]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: fmul_ss - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[FMUL:%[0-9]+]]:vgpr(s32) = G_FMUL [[COPY1]], [[COPY2]] - ; GFX10: $vgpr0 = COPY [[FMUL]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: fmul_ss: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mul_f32_e64 v0, s2, s2 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: fmul_ss: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_mul_f32_e64 v0, s2, s2 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %result = fmul float %src, %src ret float %result } ; Ternary operation with 3 different SGPRs define amdgpu_ps float @fma_s_s_s(float inreg %src0, float inreg %src1, float inreg %src2) { - ; GFX9-LABEL: name: fma_s_s_s - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3, $sgpr4 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr4 - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[COPY2]](s32) - ; GFX9: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY3]], [[COPY4]], [[COPY5]] - ; GFX9: $vgpr0 = COPY [[FMA]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: fma_s_s_s - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3, $sgpr4 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr4 - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[COPY2]](s32) - ; GFX10: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY3]], [[COPY4]], [[COPY5]] - ; GFX10: $vgpr0 = COPY [[FMA]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: fma_s_s_s: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_mov_b32_e32 v1, s4 +; GFX9-NEXT: v_fma_f32 v0, s2, v0, v1 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: fma_s_s_s: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_mov_b32_e32 v0, s4 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: v_fma_f32 v0, s3, s2, v0 +; GFX10-NEXT: ; return to shader part epilog %result = call float @llvm.fma.f32(float %src0, float %src1, float %src2) ret float %result } ; Ternary operation with 3 identical SGPRs define amdgpu_ps float @fma_sss(float inreg %src) { - ; GFX9-LABEL: name: fma_sss - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY1]], [[COPY2]], [[COPY3]] - ; GFX9: $vgpr0 = COPY [[FMA]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: fma_sss - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY1]], [[COPY2]], [[COPY3]] - ; GFX10: $vgpr0 = COPY [[FMA]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: fma_sss: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_fma_f32 v0, s2, s2, s2 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: fma_sss: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_fma_f32 v0, s2, s2, s2 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %result = call float @llvm.fma.f32(float %src, float %src, float %src) ret float %result } ; src0/1 are same SGPR define amdgpu_ps float @fma_ss_s(float inreg %src01, float inreg %src2) { - ; GFX9-LABEL: name: fma_ss_s - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY2]], [[COPY3]], [[COPY4]] - ; GFX9: $vgpr0 = COPY [[FMA]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: fma_ss_s - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY2]], [[COPY3]], [[COPY4]] - ; GFX10: $vgpr0 = COPY [[FMA]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: fma_ss_s: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_fma_f32 v0, s2, s2, v0 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: fma_ss_s: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_fma_f32 v0, s2, s2, s3 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %result = call float @llvm.fma.f32(float %src01, float %src01, float %src2) ret float %result } ; src1/2 are same SGPR define amdgpu_ps float @fma_s_ss(float inreg %src0, float inreg %src12) { - ; GFX9-LABEL: name: fma_s_ss - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY2]], [[COPY3]], [[COPY4]] - ; GFX9: $vgpr0 = COPY [[FMA]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: fma_s_ss - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY2]], [[COPY3]], [[COPY4]] - ; GFX10: $vgpr0 = COPY [[FMA]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: fma_s_ss: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_fma_f32 v0, s2, v0, v0 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: fma_s_ss: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_fma_f32 v0, s2, s3, s3 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %result = call float @llvm.fma.f32(float %src0, float %src12, float %src12) ret float %result } ; src0/2 are same SGPR define amdgpu_ps float @fma_ss_s_same_outer(float inreg %src02, float inreg %src1) { - ; GFX9-LABEL: name: fma_ss_s_same_outer - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY2]], [[COPY3]], [[COPY4]] - ; GFX9: $vgpr0 = COPY [[FMA]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: fma_ss_s_same_outer - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[FMA:%[0-9]+]]:vgpr(s32) = G_FMA [[COPY2]], [[COPY3]], [[COPY4]] - ; GFX10: $vgpr0 = COPY [[FMA]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: fma_ss_s_same_outer: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_fma_f32 v0, s2, v0, s2 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: fma_ss_s_same_outer: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_fma_f32 v0, s2, s3, s2 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %result = call float @llvm.fma.f32(float %src02, float %src1, float %src02) ret float %result } define amdgpu_ps float @fcmp_s_s(float inreg %src0, float inreg %src1) { - ; GFX9-LABEL: name: fcmp_s_s - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[FCMP:%[0-9]+]]:vcc(s1) = G_FCMP floatpred(oeq), [[COPY]](s32), [[COPY2]] - ; GFX9: [[C:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 0.000000e+00 - ; GFX9: [[C1:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 1.000000e+00 - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[C1]](s32) - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[C]](s32) - ; GFX9: [[SELECT:%[0-9]+]]:vgpr(s32) = G_SELECT [[FCMP]](s1), [[COPY3]], [[COPY4]] - ; GFX9: $vgpr0 = COPY [[SELECT]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: fcmp_s_s - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[FCMP:%[0-9]+]]:vcc(s1) = G_FCMP floatpred(oeq), [[COPY]](s32), [[COPY2]] - ; GFX10: [[C:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 0.000000e+00 - ; GFX10: [[C1:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 1.000000e+00 - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[C1]](s32) - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[C]](s32) - ; GFX10: [[SELECT:%[0-9]+]]:vgpr(s32) = G_SELECT [[FCMP]](s1), [[COPY3]], [[COPY4]] - ; GFX10: $vgpr0 = COPY [[SELECT]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: fcmp_s_s: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_cmp_eq_f32_e32 vcc, s2, v0 +; GFX9-NEXT: v_cndmask_b32_e64 v0, 0, 1.0, vcc +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: fcmp_s_s: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_cmp_eq_f32_e64 s0, s2, s3 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: v_cndmask_b32_e64 v0, 0, 1.0, s0 +; GFX10-NEXT: ; return to shader part epilog %cmp = fcmp oeq float %src0, %src1 %result = select i1 %cmp, float 1.0, float 0.0 ret float %result } define amdgpu_ps float @select_vcc_s_s(float %cmp0, float %cmp1, float inreg %src0, float inreg %src1) { - ; GFX9-LABEL: name: select_vcc_s_s - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3, $vgpr0, $vgpr1 - ; GFX9: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 - ; GFX9: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 - ; GFX9: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY3:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[FCMP:%[0-9]+]]:vcc(s1) = G_FCMP floatpred(oeq), [[COPY]](s32), [[COPY1]] - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY2]](s32) - ; GFX9: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[COPY3]](s32) - ; GFX9: [[SELECT:%[0-9]+]]:vgpr(s32) = G_SELECT [[FCMP]](s1), [[COPY4]], [[COPY5]] - ; GFX9: $vgpr0 = COPY [[SELECT]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: select_vcc_s_s - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3, $vgpr0, $vgpr1 - ; GFX10: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 - ; GFX10: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 - ; GFX10: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY3:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[FCMP:%[0-9]+]]:vcc(s1) = G_FCMP floatpred(oeq), [[COPY]](s32), [[COPY1]] - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY2]](s32) - ; GFX10: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[COPY3]](s32) - ; GFX10: [[SELECT:%[0-9]+]]:vgpr(s32) = G_SELECT [[FCMP]](s1), [[COPY4]], [[COPY5]] - ; GFX10: $vgpr0 = COPY [[SELECT]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: select_vcc_s_s: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v2, s2 +; GFX9-NEXT: v_mov_b32_e32 v3, s3 +; GFX9-NEXT: v_cmp_eq_f32_e32 vcc, v0, v1 +; GFX9-NEXT: v_cndmask_b32_e32 v0, v3, v2, vcc +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: select_vcc_s_s: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_mov_b32_e32 v2, s3 +; GFX10-NEXT: v_cmp_eq_f32_e32 vcc_lo, v0, v1 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: v_cndmask_b32_e64 v0, v2, s2, vcc_lo +; GFX10-NEXT: ; return to shader part epilog %cmp = fcmp oeq float %cmp0, %cmp1 %result = select i1 %cmp, float %src0, float %src1 ret float %result } define amdgpu_ps float @select_vcc_fneg_s_s(float %cmp0, float %cmp1, float inreg %src0, float inreg %src1) { - ; GFX9-LABEL: name: select_vcc_fneg_s_s - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3, $vgpr0, $vgpr1 - ; GFX9: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 - ; GFX9: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 - ; GFX9: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY3:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[FCMP:%[0-9]+]]:vcc(s1) = G_FCMP floatpred(oeq), [[COPY]](s32), [[COPY1]] - ; GFX9: [[FNEG:%[0-9]+]]:sgpr(s32) = G_FNEG [[COPY2]] - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[FNEG]](s32) - ; GFX9: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[COPY3]](s32) - ; GFX9: [[SELECT:%[0-9]+]]:vgpr(s32) = G_SELECT [[FCMP]](s1), [[COPY4]], [[COPY5]] - ; GFX9: $vgpr0 = COPY [[SELECT]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: select_vcc_fneg_s_s - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3, $vgpr0, $vgpr1 - ; GFX10: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 - ; GFX10: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr1 - ; GFX10: [[COPY2:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY3:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[FCMP:%[0-9]+]]:vcc(s1) = G_FCMP floatpred(oeq), [[COPY]](s32), [[COPY1]] - ; GFX10: [[FNEG:%[0-9]+]]:sgpr(s32) = G_FNEG [[COPY2]] - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[FNEG]](s32) - ; GFX10: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[COPY3]](s32) - ; GFX10: [[SELECT:%[0-9]+]]:vgpr(s32) = G_SELECT [[FCMP]](s1), [[COPY4]], [[COPY5]] - ; GFX10: $vgpr0 = COPY [[SELECT]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: select_vcc_fneg_s_s: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v2, s3 +; GFX9-NEXT: v_mov_b32_e32 v3, s2 +; GFX9-NEXT: v_cmp_eq_f32_e32 vcc, v0, v1 +; GFX9-NEXT: v_cndmask_b32_e64 v0, v2, -v3, vcc +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: select_vcc_fneg_s_s: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_mov_b32_e32 v2, s2 +; GFX10-NEXT: v_cmp_eq_f32_e32 vcc_lo, v0, v1 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: v_cndmask_b32_e64 v0, s3, -v2, vcc_lo +; GFX10-NEXT: ; return to shader part epilog %cmp = fcmp oeq float %cmp0, %cmp1 %neg.src0 = fneg float %src0 %result = select i1 %cmp, float %neg.src0, float %src1 @@ -297,122 +185,73 @@ define amdgpu_ps float @select_vcc_fneg_s_s(float %cmp0, float %cmp1, float inre ; Constant bus used by vcc define amdgpu_ps float @amdgcn_div_fmas_sss(float inreg %src, float %cmp.src) { - ; GFX9-LABEL: name: amdgcn_div_fmas_sss - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $vgpr0 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 - ; GFX9: [[C:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 0.000000e+00 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[C]](s32) - ; GFX9: [[FCMP:%[0-9]+]]:vcc(s1) = G_FCMP floatpred(oeq), [[COPY1]](s32), [[COPY2]] - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[INT:%[0-9]+]]:vgpr(s32) = G_INTRINSIC intrinsic(@llvm.amdgcn.div.fmas), [[COPY3]](s32), [[COPY4]](s32), [[COPY5]](s32), [[FCMP]](s1) - ; GFX9: $vgpr0 = COPY [[INT]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: amdgcn_div_fmas_sss - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $vgpr0 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:vgpr(s32) = COPY $vgpr0 - ; GFX10: [[C:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 0.000000e+00 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[C]](s32) - ; GFX10: [[FCMP:%[0-9]+]]:vcc(s1) = G_FCMP floatpred(oeq), [[COPY1]](s32), [[COPY2]] - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[INT:%[0-9]+]]:vgpr(s32) = G_INTRINSIC intrinsic(@llvm.amdgcn.div.fmas), [[COPY3]](s32), [[COPY4]](s32), [[COPY5]](s32), [[FCMP]](s1) - ; GFX10: $vgpr0 = COPY [[INT]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: amdgcn_div_fmas_sss: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_cmp_eq_f32_e32 vcc, 0, v0 +; GFX9-NEXT: v_mov_b32_e32 v0, s2 +; GFX9-NEXT: s_nop 2 +; GFX9-NEXT: v_div_fmas_f32 v0, v0, v0, v0 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: amdgcn_div_fmas_sss: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_cmp_eq_f32_e32 vcc_lo, 0, v0 +; GFX10-NEXT: v_div_fmas_f32 v0, s2, s2, s2 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %vcc = fcmp oeq float %cmp.src, 0.0 %result = call float @llvm.amdgcn.div.fmas.f32(float %src, float %src, float %src, i1 %vcc) ret float %result } define amdgpu_ps float @class_s_s(float inreg %src0, i32 inreg %src1) { - ; GFX9-LABEL: name: class_s_s - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[INT:%[0-9]+]]:vcc(s1) = G_INTRINSIC intrinsic(@llvm.amdgcn.class), [[COPY2]](s32), [[COPY3]](s32) - ; GFX9: [[C:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 0.000000e+00 - ; GFX9: [[C1:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 1.000000e+00 - ; GFX9: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[C1]](s32) - ; GFX9: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[C]](s32) - ; GFX9: [[SELECT:%[0-9]+]]:vgpr(s32) = G_SELECT [[INT]](s1), [[COPY4]], [[COPY5]] - ; GFX9: $vgpr0 = COPY [[SELECT]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: class_s_s - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[INT:%[0-9]+]]:vcc(s1) = G_INTRINSIC intrinsic(@llvm.amdgcn.class), [[COPY2]](s32), [[COPY3]](s32) - ; GFX10: [[C:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 0.000000e+00 - ; GFX10: [[C1:%[0-9]+]]:sgpr(s32) = G_FCONSTANT float 1.000000e+00 - ; GFX10: [[COPY4:%[0-9]+]]:vgpr(s32) = COPY [[C1]](s32) - ; GFX10: [[COPY5:%[0-9]+]]:vgpr(s32) = COPY [[C]](s32) - ; GFX10: [[SELECT:%[0-9]+]]:vgpr(s32) = G_SELECT [[INT]](s1), [[COPY4]], [[COPY5]] - ; GFX10: $vgpr0 = COPY [[SELECT]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: class_s_s: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_cmp_class_f32_e32 vcc, s2, v0 +; GFX9-NEXT: v_cndmask_b32_e64 v0, 0, 1.0, vcc +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: class_s_s: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_cmp_class_f32_e64 s0, s2, s3 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: v_cndmask_b32_e64 v0, 0, 1.0, s0 +; GFX10-NEXT: ; return to shader part epilog %class = call i1 @llvm.amdgcn.class.f32(float %src0, i32 %src1) %result = select i1 %class, float 1.0, float 0.0 ret float %result } define amdgpu_ps float @div_scale_s_s_true(float inreg %src0, float inreg %src1) { - ; GFX9-LABEL: name: div_scale_s_s_true - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[INT:%[0-9]+]]:vgpr(s32), [[INT1:%[0-9]+]]:vcc(s1) = G_INTRINSIC intrinsic(@llvm.amdgcn.div.scale), [[COPY2]](s32), [[COPY3]](s32), -1 - ; GFX9: $vgpr0 = COPY [[INT]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: div_scale_s_s_true - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[INT:%[0-9]+]]:vgpr(s32), [[INT1:%[0-9]+]]:vcc(s1) = G_INTRINSIC intrinsic(@llvm.amdgcn.div.scale), [[COPY2]](s32), [[COPY3]](s32), -1 - ; GFX10: $vgpr0 = COPY [[INT]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: div_scale_s_s_true: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_div_scale_f32 v0, s[0:1], s2, v0, s2 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: div_scale_s_s_true: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_div_scale_f32 v0, s0, s2, s3, s2 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %div.scale = call { float, i1 } @llvm.amdgcn.div.scale.f32(float %src0, float %src1, i1 true) %result = extractvalue { float, i1 } %div.scale, 0 ret float %result } define amdgpu_ps float @div_scale_s_s_false(float inreg %src0, float inreg %src1) { - ; GFX9-LABEL: name: div_scale_s_s_false - ; GFX9: bb.1 (%ir-block.0): - ; GFX9: liveins: $sgpr2, $sgpr3 - ; GFX9: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX9: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX9: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX9: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX9: [[INT:%[0-9]+]]:vgpr(s32), [[INT1:%[0-9]+]]:vcc(s1) = G_INTRINSIC intrinsic(@llvm.amdgcn.div.scale), [[COPY2]](s32), [[COPY3]](s32), 0 - ; GFX9: $vgpr0 = COPY [[INT]](s32) - ; GFX9: SI_RETURN_TO_EPILOG implicit $vgpr0 - ; GFX10-LABEL: name: div_scale_s_s_false - ; GFX10: bb.1 (%ir-block.0): - ; GFX10: liveins: $sgpr2, $sgpr3 - ; GFX10: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr2 - ; GFX10: [[COPY1:%[0-9]+]]:sgpr(s32) = COPY $sgpr3 - ; GFX10: [[COPY2:%[0-9]+]]:vgpr(s32) = COPY [[COPY]](s32) - ; GFX10: [[COPY3:%[0-9]+]]:vgpr(s32) = COPY [[COPY1]](s32) - ; GFX10: [[INT:%[0-9]+]]:vgpr(s32), [[INT1:%[0-9]+]]:vcc(s1) = G_INTRINSIC intrinsic(@llvm.amdgcn.div.scale), [[COPY2]](s32), [[COPY3]](s32), 0 - ; GFX10: $vgpr0 = COPY [[INT]](s32) - ; GFX10: SI_RETURN_TO_EPILOG implicit $vgpr0 +; GFX9-LABEL: div_scale_s_s_false: +; GFX9: ; %bb.0: +; GFX9-NEXT: v_mov_b32_e32 v0, s3 +; GFX9-NEXT: v_div_scale_f32 v0, s[0:1], v0, v0, s2 +; GFX9-NEXT: ; return to shader part epilog +; +; GFX10-LABEL: div_scale_s_s_false: +; GFX10: ; %bb.0: +; GFX10-NEXT: v_div_scale_f32 v0, s0, s3, s3, s2 +; GFX10-NEXT: ; implicit-def: $vcc_hi +; GFX10-NEXT: ; return to shader part epilog %div.scale = call { float, i1 } @llvm.amdgcn.div.scale.f32(float %src0, float %src1, i1 false) %result = extractvalue { float, i1 } %div.scale, 0 ret float %result diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ds.ordered.add.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ds.ordered.add.ll index 8cba08f016daf..4193d976afd65 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ds.ordered.add.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ds.ordered.add.ll @@ -1,5 +1,4 @@ -; FIXME: Broken SI run line -; XUN: llc -global-isel -march=amdgcn -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.add.ll | FileCheck -check-prefixes=GCN,FUNC %S/../llvm.amdgcn.ds.ordered.add.ll +; RUN: llc -global-isel -march=amdgcn -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.add.ll | FileCheck -check-prefixes=GCN,FUNC %S/../llvm.amdgcn.ds.ordered.add.ll ; RUN: llc -global-isel -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.add.ll | FileCheck -check-prefixes=GCN,FUNC %S/../llvm.amdgcn.ds.ordered.add.ll ; RUN: llc -global-isel -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.add.ll | FileCheck -check-prefixes=GCN,VIGFX9,FUNC %S/../llvm.amdgcn.ds.ordered.add.ll ; RUN: llc -global-isel -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.add.ll | FileCheck -check-prefixes=GCN,VIGFX9,FUNC %S/../llvm.amdgcn.ds.ordered.add.ll diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ds.ordered.swap.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ds.ordered.swap.ll index 28c2c7a4e9bfb..e2c3b625395a7 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ds.ordered.swap.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.ds.ordered.swap.ll @@ -1,5 +1,4 @@ -; FIXME: Broken SI run line -; XUN: llc -global-isel -march=amdgcn -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.swap.ll | FileCheck -check-prefixes=GCN,FUNC %S/../llvm.amdgcn.ds.ordered.swap.ll +; RUN: llc -global-isel -march=amdgcn -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.swap.ll | FileCheck -check-prefixes=GCN,FUNC %S/../llvm.amdgcn.ds.ordered.swap.ll ; RUN: llc -global-isel -march=amdgcn -mcpu=bonaire -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.swap.ll | FileCheck -check-prefixes=GCN,FUNC %S/../llvm.amdgcn.ds.ordered.swap.ll ; RUN: llc -global-isel -march=amdgcn -mcpu=tonga -mattr=-flat-for-global -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.swap.ll | FileCheck -check-prefixes=GCN,VIGFX9,FUNC %S/../llvm.amdgcn.ds.ordered.swap.ll ; RUN: llc -global-isel -march=amdgcn -mcpu=gfx900 -verify-machineinstrs < %S/../llvm.amdgcn.ds.ordered.swap.ll | FileCheck -check-prefixes=GCN,VIGFX9,FUNC %S/../llvm.amdgcn.ds.ordered.swap.ll diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll index 5389adf5a526e..7d116f8e8925f 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.sbfe.ll @@ -687,14 +687,48 @@ define amdgpu_kernel void @bfe_sext_in_reg_i24(i32 addrspace(1)* %out, i32 addrs ret void } -; FIXME -; define amdgpu_kernel void @simplify_demanded_bfe_sdiv(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { -; %src = load i32, i32 addrspace(1)* %in, align 4 -; %bfe = call i32 @llvm.amdgcn.sbfe.i32(i32 %src, i32 1, i32 16) -; %div = sdiv i32 %bfe, 2 -; store i32 %div, i32 addrspace(1)* %out, align 4 -; ret void -; } +define amdgpu_kernel void @simplify_demanded_bfe_sdiv(i32 addrspace(1)* %out, i32 addrspace(1)* %in) #0 { +; GFX6-LABEL: simplify_demanded_bfe_sdiv: +; GFX6: ; %bb.0: +; GFX6-NEXT: v_cvt_f32_ubyte0_e32 v0, 2 +; GFX6-NEXT: v_rcp_iflag_f32_e32 v0, v0 +; GFX6-NEXT: s_load_dwordx2 s[2:3], s[0:1], 0xb +; GFX6-NEXT: s_load_dwordx2 s[4:5], s[0:1], 0x9 +; GFX6-NEXT: s_mov_b32 s6, -1 +; GFX6-NEXT: v_mul_f32_e32 v0, 0x4f7ffffe, v0 +; GFX6-NEXT: v_cvt_u32_f32_e32 v0, v0 +; GFX6-NEXT: s_waitcnt lgkmcnt(0) +; GFX6-NEXT: s_load_dword s2, s[2:3], 0x0 +; GFX6-NEXT: s_mov_b32 s7, 0xf000 +; GFX6-NEXT: v_mul_lo_u32 v1, -2, v0 +; GFX6-NEXT: s_waitcnt lgkmcnt(0) +; GFX6-NEXT: s_bfe_i32 s2, s2, 0x100001 +; GFX6-NEXT: s_ashr_i32 s3, s2, 31 +; GFX6-NEXT: v_mul_hi_u32 v1, v0, v1 +; GFX6-NEXT: s_add_i32 s2, s2, s3 +; GFX6-NEXT: s_xor_b32 s2, s2, s3 +; GFX6-NEXT: v_add_i32_e32 v0, vcc, v0, v1 +; GFX6-NEXT: v_mul_hi_u32 v0, s2, v0 +; GFX6-NEXT: v_lshlrev_b32_e32 v1, 1, v0 +; GFX6-NEXT: v_add_i32_e32 v2, vcc, 1, v0 +; GFX6-NEXT: v_sub_i32_e32 v1, vcc, s2, v1 +; GFX6-NEXT: v_cmp_le_u32_e32 vcc, 2, v1 +; GFX6-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc +; GFX6-NEXT: v_subrev_i32_e64 v2, s[0:1], 2, v1 +; GFX6-NEXT: v_cndmask_b32_e32 v1, v1, v2, vcc +; GFX6-NEXT: v_add_i32_e32 v2, vcc, 1, v0 +; GFX6-NEXT: v_cmp_le_u32_e32 vcc, 2, v1 +; GFX6-NEXT: v_cndmask_b32_e32 v0, v0, v2, vcc +; GFX6-NEXT: v_xor_b32_e32 v0, s3, v0 +; GFX6-NEXT: v_subrev_i32_e32 v0, vcc, s3, v0 +; GFX6-NEXT: buffer_store_dword v0, off, s[4:7], 0 +; GFX6-NEXT: s_endpgm + %src = load i32, i32 addrspace(1)* %in, align 4 + %bfe = call i32 @llvm.amdgcn.sbfe.i32(i32 %src, i32 1, i32 16) + %div = sdiv i32 %bfe, 2 + store i32 %div, i32 addrspace(1)* %out, align 4 + ret void +} define amdgpu_kernel void @bfe_0_width(i32 addrspace(1)* %out, i32 addrspace(1)* %ptr) #0 { ; GFX6-LABEL: bfe_0_width: diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/xnor.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/xnor.ll index a8631a18de3cd..2512aaaeb082c 100644 --- a/llvm/test/CodeGen/AMDGPU/GlobalISel/xnor.ll +++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/xnor.ll @@ -15,14 +15,58 @@ entry: ret i32 %r0.val } -; FIXME: -; define amdgpu_ps i32 @scalar_xnor_v2i16_one_use(<2 x i16> inreg %a, <2 x i16> inreg %b) { -; entry: -; %xor = xor <2 x i16> %a, %b -; %r0.val = xor <2 x i16> %xor, -; %cast = bitcast <2 x i16> %r0.val to i32 -; ret i32 %cast -; } +; FIXME: fails to match +define amdgpu_ps i32 @scalar_xnor_v2i16_one_use(<2 x i16> inreg %a, <2 x i16> inreg %b) { +; GFX7-LABEL: scalar_xnor_v2i16_one_use: +; GFX7: ; %bb.0: ; %entry +; GFX7-NEXT: s_mov_b32 s4, 0xffff +; GFX7-NEXT: s_lshl_b32 s1, s1, 16 +; GFX7-NEXT: s_and_b32 s0, s0, s4 +; GFX7-NEXT: s_or_b32 s0, s1, s0 +; GFX7-NEXT: s_lshl_b32 s1, s3, 16 +; GFX7-NEXT: s_and_b32 s2, s2, s4 +; GFX7-NEXT: s_or_b32 s1, s1, s2 +; GFX7-NEXT: s_xor_b32 s0, s0, s1 +; GFX7-NEXT: s_xor_b32 s0, s0, -1 +; GFX7-NEXT: ; return to shader part epilog +; +; GFX8-LABEL: scalar_xnor_v2i16_one_use: +; GFX8: ; %bb.0: ; %entry +; GFX8-NEXT: s_mov_b32 s2, 0xffff +; GFX8-NEXT: s_lshr_b32 s5, s0, 16 +; GFX8-NEXT: s_lshr_b32 s6, s1, 16 +; GFX8-NEXT: s_and_b32 s4, s0, s2 +; GFX8-NEXT: s_and_b32 s0, s1, s2 +; GFX8-NEXT: s_and_b32 s5, s5, s2 +; GFX8-NEXT: s_and_b32 s1, s6, s2 +; GFX8-NEXT: s_mov_b32 s3, s2 +; GFX8-NEXT: s_xor_b64 s[0:1], s[4:5], s[0:1] +; GFX8-NEXT: s_and_b64 s[0:1], s[0:1], s[2:3] +; GFX8-NEXT: s_xor_b64 s[0:1], s[0:1], s[2:3] +; GFX8-NEXT: s_lshl_b32 s1, s1, 16 +; GFX8-NEXT: s_and_b32 s0, s0, s2 +; GFX8-NEXT: s_or_b32 s0, s1, s0 +; GFX8-NEXT: ; return to shader part epilog +; +; GFX900-LABEL: scalar_xnor_v2i16_one_use: +; GFX900: ; %bb.0: ; %entry +; GFX900-NEXT: s_pack_ll_b32_b16 s2, -1, -1 +; GFX900-NEXT: s_xor_b32 s0, s0, s1 +; GFX900-NEXT: s_xor_b32 s0, s0, s2 +; GFX900-NEXT: ; return to shader part epilog +; +; GFX906-LABEL: scalar_xnor_v2i16_one_use: +; GFX906: ; %bb.0: ; %entry +; GFX906-NEXT: s_pack_ll_b32_b16 s2, -1, -1 +; GFX906-NEXT: s_xor_b32 s0, s0, s1 +; GFX906-NEXT: s_xor_b32 s0, s0, s2 +; GFX906-NEXT: ; return to shader part epilog +entry: + %xor = xor <2 x i16> %a, %b + %r0.val = xor <2 x i16> %xor, + %cast = bitcast <2 x i16> %r0.val to i32 + ret i32 %cast +} define amdgpu_ps <2 x i32> @scalar_xnor_i32_mul_use(i32 inreg %a, i32 inreg %b) { ; GCN-LABEL: scalar_xnor_i32_mul_use: @@ -51,13 +95,79 @@ define amdgpu_ps i64 @scalar_xnor_i64_one_use(i64 inreg %a, i64 inreg %b) { ret i64 %r0.val } -; FIXME: -; define amdgpu_ps i64 @scalar_xnor_v4i16_one_use(<4 x i16> inreg %a, <4 x i16> inreg %b) { -; %xor = xor <4 x i16> %a, %b -; %ret = xor <4 x i16> %xor, -; %cast = bitcast <4 x i16> %ret to i64 -; ret i64 %cast -; } +; FIXME: fails to match +define amdgpu_ps i64 @scalar_xnor_v4i16_one_use(<4 x i16> inreg %a, <4 x i16> inreg %b) { +; GFX7-LABEL: scalar_xnor_v4i16_one_use: +; GFX7: ; %bb.0: +; GFX7-NEXT: s_mov_b32 s8, 0xffff +; GFX7-NEXT: s_lshl_b32 s1, s1, 16 +; GFX7-NEXT: s_and_b32 s0, s0, s8 +; GFX7-NEXT: s_or_b32 s0, s1, s0 +; GFX7-NEXT: s_lshl_b32 s1, s3, 16 +; GFX7-NEXT: s_and_b32 s2, s2, s8 +; GFX7-NEXT: s_or_b32 s1, s1, s2 +; GFX7-NEXT: s_and_b32 s3, s4, s8 +; GFX7-NEXT: s_lshl_b32 s2, s5, 16 +; GFX7-NEXT: s_or_b32 s2, s2, s3 +; GFX7-NEXT: s_lshl_b32 s3, s7, 16 +; GFX7-NEXT: s_and_b32 s4, s6, s8 +; GFX7-NEXT: s_or_b32 s3, s3, s4 +; GFX7-NEXT: s_mov_b32 s4, -1 +; GFX7-NEXT: s_mov_b32 s5, s4 +; GFX7-NEXT: s_xor_b64 s[0:1], s[0:1], s[2:3] +; GFX7-NEXT: s_xor_b64 s[0:1], s[0:1], s[4:5] +; GFX7-NEXT: ; return to shader part epilog +; +; GFX8-LABEL: scalar_xnor_v4i16_one_use: +; GFX8: ; %bb.0: +; GFX8-NEXT: s_mov_b32 s4, 0xffff +; GFX8-NEXT: s_lshr_b32 s5, s0, 16 +; GFX8-NEXT: s_and_b32 s7, s5, s4 +; GFX8-NEXT: s_lshr_b32 s5, s1, 16 +; GFX8-NEXT: s_and_b32 s6, s0, s4 +; GFX8-NEXT: s_and_b32 s0, s1, s4 +; GFX8-NEXT: s_and_b32 s1, s5, s4 +; GFX8-NEXT: s_lshr_b32 s5, s2, 16 +; GFX8-NEXT: s_and_b32 s8, s2, s4 +; GFX8-NEXT: s_and_b32 s9, s5, s4 +; GFX8-NEXT: s_lshr_b32 s5, s3, 16 +; GFX8-NEXT: s_and_b32 s2, s3, s4 +; GFX8-NEXT: s_and_b32 s3, s5, s4 +; GFX8-NEXT: s_xor_b64 s[6:7], s[6:7], s[8:9] +; GFX8-NEXT: s_mov_b32 s5, s4 +; GFX8-NEXT: s_xor_b64 s[0:1], s[0:1], s[2:3] +; GFX8-NEXT: s_and_b64 s[2:3], s[6:7], s[4:5] +; GFX8-NEXT: s_and_b64 s[0:1], s[0:1], s[4:5] +; GFX8-NEXT: s_xor_b64 s[2:3], s[2:3], s[4:5] +; GFX8-NEXT: s_xor_b64 s[6:7], s[0:1], s[4:5] +; GFX8-NEXT: s_and_b32 s1, s2, s4 +; GFX8-NEXT: s_lshl_b32 s0, s3, 16 +; GFX8-NEXT: s_or_b32 s0, s0, s1 +; GFX8-NEXT: s_lshl_b32 s1, s7, 16 +; GFX8-NEXT: s_and_b32 s2, s6, s4 +; GFX8-NEXT: s_or_b32 s1, s1, s2 +; GFX8-NEXT: ; return to shader part epilog +; +; GFX900-LABEL: scalar_xnor_v4i16_one_use: +; GFX900: ; %bb.0: +; GFX900-NEXT: s_pack_ll_b32_b16 s4, -1, -1 +; GFX900-NEXT: s_mov_b32 s5, s4 +; GFX900-NEXT: s_xor_b64 s[0:1], s[0:1], s[2:3] +; GFX900-NEXT: s_xor_b64 s[0:1], s[0:1], s[4:5] +; GFX900-NEXT: ; return to shader part epilog +; +; GFX906-LABEL: scalar_xnor_v4i16_one_use: +; GFX906: ; %bb.0: +; GFX906-NEXT: s_pack_ll_b32_b16 s4, -1, -1 +; GFX906-NEXT: s_mov_b32 s5, s4 +; GFX906-NEXT: s_xor_b64 s[0:1], s[0:1], s[2:3] +; GFX906-NEXT: s_xor_b64 s[0:1], s[0:1], s[4:5] +; GFX906-NEXT: ; return to shader part epilog + %xor = xor <4 x i16> %a, %b + %ret = xor <4 x i16> %xor, + %cast = bitcast <4 x i16> %ret to i64 + ret i64 %cast +} define amdgpu_ps <2 x i64> @scalar_xnor_i64_mul_use(i64 inreg %a, i64 inreg %b) { ; GCN-LABEL: scalar_xnor_i64_mul_use: From 7b16fd8a2514287765cdcdb09b9059d5d9a2933a Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 18 Jul 2020 17:30:42 +0300 Subject: [PATCH 716/771] [NFC][CVP] Add tests for possible sdiv->udiv where operands are not non-negative Currently that fold requires both operands to be non-negative, but the only real requirement for the fold is that we must know the domains of the operands. --- .../CorrelatedValuePropagation/sdiv.ll | 173 +++++++++++++++++- 1 file changed, 163 insertions(+), 10 deletions(-) diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll b/llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll index b037bfaee7a21..ec5de0010a14f 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll @@ -1,7 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -correlated-propagation -S | FileCheck %s -; CHECK-LABEL: @test0( +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + define void @test0(i32 %n) { +; CHECK-LABEL: @test0( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[FOR_BODY:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[J_0]], 1 +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[DIV1]] = udiv i32 [[J_0]], 2 +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; entry: br label %for.cond @@ -11,7 +26,6 @@ for.cond: ; preds = %for.body, %entry br i1 %cmp, label %for.body, label %for.end for.body: ; preds = %for.cond -; CHECK: %div1 = udiv i32 %j.0, 2 %div = sdiv i32 %j.0, 2 br label %for.cond @@ -19,8 +33,20 @@ for.end: ; preds = %for.cond ret void } -; CHECK-LABEL: @test1( define void @test1(i32 %n) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ [[N:%.*]], [[ENTRY:%.*]] ], [ [[DIV:%.*]], [[FOR_BODY:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[J_0]], -2 +; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[DIV]] = sdiv i32 [[J_0]], 2 +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; entry: br label %for.cond @@ -30,7 +56,6 @@ for.cond: ; preds = %for.body, %entry br i1 %cmp, label %for.body, label %for.end for.body: ; preds = %for.cond -; CHECK: %div = sdiv i32 %j.0, 2 %div = sdiv i32 %j.0, 2 br label %for.cond @@ -38,14 +63,22 @@ for.end: ; preds = %for.cond ret void } -; CHECK-LABEL: @test2( define void @test2(i32 %n) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 1 +; CHECK-NEXT: br i1 [[CMP]], label [[BB:%.*]], label [[EXIT:%.*]] +; CHECK: bb: +; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[N]], 2 +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: %cmp = icmp sgt i32 %n, 1 br i1 %cmp, label %bb, label %exit bb: -; CHECK: %div1 = udiv i32 %n, 2 %div = sdiv i32 %n, 2 br label %exit @@ -57,14 +90,25 @@ exit: ; at the point of sdiv, we know that %a is always greater than 0, ; because of the guard before it, so we can transform it to udiv. declare void @llvm.experimental.guard(i1,...) -; CHECK-LABEL: @test4 define void @test4(i32 %n) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[LOOP:%.*]], label [[EXIT:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[A]], 4 +; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND]]) [ "deopt"() ] +; CHECK-NEXT: [[DIV1]] = udiv i32 [[A]], 6 +; CHECK-NEXT: br i1 [[COND]], label [[LOOP]], label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: %cmp = icmp sgt i32 %n, 0 br i1 %cmp, label %loop, label %exit loop: -; CHECK: udiv i32 %a, 6 %a = phi i32 [ %n, %entry ], [ %div, %loop ] %cond = icmp sgt i32 %a, 4 call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ] @@ -77,14 +121,26 @@ exit: ; same test as above with assume instead of guard. declare void @llvm.assume(i1) -; CHECK-LABEL: @test5 define void @test5(i32 %n) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[LOOP:%.*]], label [[EXIT:%.*]] +; CHECK: loop: +; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], [[ENTRY:%.*]] ], [ [[DIV1:%.*]], [[LOOP]] ] +; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[A]], 4 +; CHECK-NEXT: call void @llvm.assume(i1 [[COND]]) +; CHECK-NEXT: [[DIV1]] = udiv i32 [[A]], 6 +; CHECK-NEXT: [[LOOPCOND:%.*]] = icmp sgt i32 [[DIV1]], 8 +; CHECK-NEXT: br i1 [[LOOPCOND]], label [[LOOP]], label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: ret void +; entry: %cmp = icmp sgt i32 %n, 0 br i1 %cmp, label %loop, label %exit loop: -; CHECK: udiv i32 %a, 6 %a = phi i32 [ %n, %entry ], [ %div, %loop ] %cond = icmp sgt i32 %a, 4 call void @llvm.assume(i1 %cond) @@ -95,3 +151,100 @@ loop: exit: ret void } + +; Now, let's try various domain combinations for operands. + +define i32 @test6_pos_pos(i32 %x, i32 %y) { +; CHECK-LABEL: @test6_pos_pos( +; CHECK-NEXT: [[C0:%.*]] = icmp sge i32 [[X:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) +; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) +; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X]], [[Y]] +; CHECK-NEXT: ret i32 [[DIV1]] +; + %c0 = icmp sge i32 %x, 0 + call void @llvm.assume(i1 %c0) + %c1 = icmp sge i32 %y, 0 + call void @llvm.assume(i1 %c1) + + %div = sdiv i32 %x, %y + ret i32 %div +} +define i32 @test7_pos_neg(i32 %x, i32 %y) { +; CHECK-LABEL: @test7_pos_neg( +; CHECK-NEXT: [[C0:%.*]] = icmp sge i32 [[X:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) +; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c0 = icmp sge i32 %x, 0 + call void @llvm.assume(i1 %c0) + %c1 = icmp sle i32 %y, 0 + call void @llvm.assume(i1 %c1) + + %div = sdiv i32 %x, %y + ret i32 %div +} +define i32 @test8_neg_pos(i32 %x, i32 %y) { +; CHECK-LABEL: @test8_neg_pos( +; CHECK-NEXT: [[C0:%.*]] = icmp sle i32 [[X:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) +; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c0 = icmp sle i32 %x, 0 + call void @llvm.assume(i1 %c0) + %c1 = icmp sge i32 %y, 0 + call void @llvm.assume(i1 %c1) + + %div = sdiv i32 %x, %y + ret i32 %div +} +define i32 @test9_neg_neg(i32 %x, i32 %y) { +; CHECK-LABEL: @test9_neg_neg( +; CHECK-NEXT: [[C0:%.*]] = icmp sle i32 [[X:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) +; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0 +; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]] +; CHECK-NEXT: ret i32 [[DIV]] +; + %c0 = icmp sle i32 %x, 0 + call void @llvm.assume(i1 %c0) + %c1 = icmp sle i32 %y, 0 + call void @llvm.assume(i1 %c1) + + %div = sdiv i32 %x, %y + ret i32 %div +} + +; After making division unsigned, can we narrow it? +define i32 @test10_narrow(i32 %x, i32 %y) { +; CHECK-LABEL: @test10_narrow( +; CHECK-NEXT: [[C0:%.*]] = icmp ult i32 [[X:%.*]], 128 +; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) +; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[Y:%.*]], 128 +; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) +; CHECK-NEXT: br label [[END:%.*]] +; CHECK: end: +; CHECK-NEXT: [[DIV1_LHS_TRUNC:%.*]] = trunc i32 [[X]] to i8 +; CHECK-NEXT: [[DIV1_RHS_TRUNC:%.*]] = trunc i32 [[Y]] to i8 +; CHECK-NEXT: [[DIV12:%.*]] = udiv i8 [[DIV1_LHS_TRUNC]], [[DIV1_RHS_TRUNC]] +; CHECK-NEXT: [[DIV1_ZEXT:%.*]] = zext i8 [[DIV12]] to i32 +; CHECK-NEXT: ret i32 [[DIV1_ZEXT]] +; + %c0 = icmp ult i32 %x, 128 + call void @llvm.assume(i1 %c0) + %c1 = icmp ult i32 %y, 128 + call void @llvm.assume(i1 %c1) + br label %end + +end: + %div = sdiv i32 %x, %y + ret i32 %div +} From 2cde6984d8fbaf9d3ce9e09ce632f7de553df5bb Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 18 Jul 2020 13:07:13 +0300 Subject: [PATCH 717/771] [NFC][CVP] Refactor isPositive() out of hasPositiveOperands() --- .../Scalar/CorrelatedValuePropagation.cpp | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index cd2f4ca36f3bb..6a18bc2d32409 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -601,14 +601,15 @@ static bool processCallSite(CallBase &CB, LazyValueInfo *LVI) { return true; } +static bool isPositive(Value *V, LazyValueInfo *LVI, Instruction *CxtI) { + Constant *Zero = ConstantInt::get(V->getType(), 0); + auto Result = LVI->getPredicateAt(ICmpInst::ICMP_SGE, V, Zero, CxtI); + return Result == LazyValueInfo::True; +} + static bool hasPositiveOperands(BinaryOperator *SDI, LazyValueInfo *LVI) { - Constant *Zero = ConstantInt::get(SDI->getType(), 0); - for (Value *O : SDI->operands()) { - auto Result = LVI->getPredicateAt(ICmpInst::ICMP_SGE, O, Zero, SDI); - if (Result != LazyValueInfo::True) - return false; - } - return true; + return all_of(SDI->operands(), + [&](Value *Op) { return isPositive(Op, LVI, SDI); }); } /// Try to shrink a udiv/urem's width down to the smallest power of two that's @@ -697,9 +698,7 @@ static bool processAShr(BinaryOperator *SDI, LazyValueInfo *LVI) { if (SDI->getType()->isVectorTy()) return false; - Constant *Zero = ConstantInt::get(SDI->getType(), 0); - if (LVI->getPredicateAt(ICmpInst::ICMP_SGE, SDI->getOperand(0), Zero, SDI) != - LazyValueInfo::True) + if (!isPositive(SDI->getOperand(0), LVI, SDI)) return false; ++NumAShrs; @@ -719,9 +718,7 @@ static bool processSExt(SExtInst *SDI, LazyValueInfo *LVI) { Value *Base = SDI->getOperand(0); - Constant *Zero = ConstantInt::get(Base->getType(), 0); - if (LVI->getPredicateAt(ICmpInst::ICMP_SGE, Base, Zero, SDI) != - LazyValueInfo::True) + if (!isPositive(Base, LVI, SDI)) return false; ++NumSExt; From 45b738882474e615ccf15e289b765bca0ccfc1d2 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 18 Jul 2020 13:13:01 +0300 Subject: [PATCH 718/771] [NFC][CVP] Rename predicates - s/positive/non negative/ to better note that zero is ok --- .../Scalar/CorrelatedValuePropagation.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 6a18bc2d32409..284312eaf8220 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -601,15 +601,15 @@ static bool processCallSite(CallBase &CB, LazyValueInfo *LVI) { return true; } -static bool isPositive(Value *V, LazyValueInfo *LVI, Instruction *CxtI) { +static bool isNonNegative(Value *V, LazyValueInfo *LVI, Instruction *CxtI) { Constant *Zero = ConstantInt::get(V->getType(), 0); auto Result = LVI->getPredicateAt(ICmpInst::ICMP_SGE, V, Zero, CxtI); return Result == LazyValueInfo::True; } -static bool hasPositiveOperands(BinaryOperator *SDI, LazyValueInfo *LVI) { +static bool allOperandsAreNonNegative(BinaryOperator *SDI, LazyValueInfo *LVI) { return all_of(SDI->operands(), - [&](Value *Op) { return isPositive(Op, LVI, SDI); }); + [&](Value *Op) { return isNonNegative(Op, LVI, SDI); }); } /// Try to shrink a udiv/urem's width down to the smallest power of two that's @@ -655,7 +655,7 @@ static bool processUDivOrURem(BinaryOperator *Instr, LazyValueInfo *LVI) { } static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) { - if (SDI->getType()->isVectorTy() || !hasPositiveOperands(SDI, LVI)) + if (SDI->getType()->isVectorTy() || !allOperandsAreNonNegative(SDI, LVI)) return false; ++NumSRems; @@ -677,7 +677,7 @@ static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) { /// conditions, this can sometimes prove conditions instcombine can't by /// exploiting range information. static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) { - if (SDI->getType()->isVectorTy() || !hasPositiveOperands(SDI, LVI)) + if (SDI->getType()->isVectorTy() || !allOperandsAreNonNegative(SDI, LVI)) return false; ++NumSDivs; @@ -698,7 +698,7 @@ static bool processAShr(BinaryOperator *SDI, LazyValueInfo *LVI) { if (SDI->getType()->isVectorTy()) return false; - if (!isPositive(SDI->getOperand(0), LVI, SDI)) + if (!isNonNegative(SDI->getOperand(0), LVI, SDI)) return false; ++NumAShrs; @@ -718,7 +718,7 @@ static bool processSExt(SExtInst *SDI, LazyValueInfo *LVI) { Value *Base = SDI->getOperand(0); - if (!isPositive(Base, LVI, SDI)) + if (!isNonNegative(Base, LVI, SDI)) return false; ++NumSExt; From 8d487668d09fb0e4e54f36207f07c1480ffabbfd Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 18 Jul 2020 13:23:26 +0300 Subject: [PATCH 719/771] [CVP] Soften SDiv into a UDiv as long as we know domains of both of the operands. Yes, if operands are non-positive this comes at the extra cost of two extra negations. But a. division is already just ridiculously costly, two more subtractions can't hurt much :) and b. we have better/more analyzes/folds for an unsigned division, we could end up narrowing it's bitwidth, converting it to lshr, etc. This is essentially a take two on 0fdcca07ad2c0bdc2cdd40ba638109926f4f513b, which didn't fix the potential regression i was seeing, because ValueTracking's computeKnownBits() doesn't make use of dominating conditions in it's analysis. While i could teach it that, this seems like the more general fix. This big hammer actually does catch said potential regression. Over vanilla test-suite + RawSpeed + darktable (10M IR instrs, 1M IR BB, 1M X86 ASM instrs), this fires/converts 5 more (+2%) SDiv's, the total instruction count at the end of middle-end pipeline is only +6, so out of +10 extra negations, ~half are folded away, and asm instr count is only +1, so practically speaking all extra negations are folded away and are therefore free. Sadly, all these new UDiv's remained, none folded away. But there are two less basic blocks. https://rise4fun.com/Alive/VS6 Name: v0 Pre: C0 >= 0 && C1 >= 0 %r = sdiv i8 C0, C1 => %r = udiv i8 C0, C1 Name: v1 Pre: C0 <= 0 && C1 >= 0 %r = sdiv i8 C0, C1 => %t0 = udiv i8 -C0, C1 %r = sub i8 0, %t0 Name: v2 Pre: C0 >= 0 && C1 <= 0 %r = sdiv i8 C0, C1 => %t0 = udiv i8 C0, -C1 %r = sub i8 0, %t0 Name: v3 Pre: C0 <= 0 && C1 <= 0 %r = sdiv i8 C0, C1 => %r = udiv i8 -C0, -C1 --- .../Scalar/CorrelatedValuePropagation.cpp | 65 ++++++++++++++++--- .../CorrelatedValuePropagation/sdiv.ll | 18 +++-- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index 284312eaf8220..fb7a005708e56 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -607,6 +607,12 @@ static bool isNonNegative(Value *V, LazyValueInfo *LVI, Instruction *CxtI) { return Result == LazyValueInfo::True; } +static bool isNonPositive(Value *V, LazyValueInfo *LVI, Instruction *CxtI) { + Constant *Zero = ConstantInt::get(V->getType(), 0); + auto Result = LVI->getPredicateAt(ICmpInst::ICMP_SLE, V, Zero, CxtI); + return Result == LazyValueInfo::True; +} + static bool allOperandsAreNonNegative(BinaryOperator *SDI, LazyValueInfo *LVI) { return all_of(SDI->operands(), [&](Value *Op) { return isNonNegative(Op, LVI, SDI); }); @@ -672,24 +678,65 @@ static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) { } /// See if LazyValueInfo's ability to exploit edge conditions or range -/// information is sufficient to prove the both operands of this SDiv are -/// positive. If this is the case, replace the SDiv with a UDiv. Even for local +/// information is sufficient to prove the signs of both operands of this SDiv. +/// If this is the case, replace the SDiv with a UDiv. Even for local /// conditions, this can sometimes prove conditions instcombine can't by /// exploiting range information. static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) { - if (SDI->getType()->isVectorTy() || !allOperandsAreNonNegative(SDI, LVI)) + if (SDI->getType()->isVectorTy()) return false; + enum class Domain { NonNegative, NonPositive, Unknown }; + auto getDomain = [&](Value *V) { + if (isNonNegative(V, LVI, SDI)) + return Domain::NonNegative; + if (isNonPositive(V, LVI, SDI)) + return Domain::NonPositive; + return Domain::Unknown; + }; + + struct Operand { + Value *V; + Domain Domain; + }; + std::array Ops; + for (const auto &I : zip(Ops, SDI->operands())) { + Operand &Op = std::get<0>(I); + Op.V = std::get<1>(I); + Op.Domain = getDomain(Op.V); + if (Op.Domain == Domain::Unknown) + return false; + } + + // We know domains of both of the operands! ++NumSDivs; - auto *BO = BinaryOperator::CreateUDiv(SDI->getOperand(0), SDI->getOperand(1), - SDI->getName(), SDI); - BO->setDebugLoc(SDI->getDebugLoc()); - BO->setIsExact(SDI->isExact()); - SDI->replaceAllUsesWith(BO); + + // We need operands to be non-negative, so negate each one that isn't. + for (Operand &Op : Ops) { + if (Op.Domain == Domain::NonNegative) + continue; + auto *BO = + BinaryOperator::CreateNeg(Op.V, Op.V->getName() + ".nonneg", SDI); + BO->setDebugLoc(SDI->getDebugLoc()); + Op.V = BO; + } + + auto *UDiv = + BinaryOperator::CreateUDiv(Ops[0].V, Ops[1].V, SDI->getName(), SDI); + UDiv->setDebugLoc(SDI->getDebugLoc()); + UDiv->setIsExact(SDI->isExact()); + + Value *Res = UDiv; + + // If the operands had two different domains, we need to negate the result. + if (Ops[0].Domain != Ops[1].Domain) + Res = BinaryOperator::CreateNeg(Res, Res->getName() + ".neg", SDI); + + SDI->replaceAllUsesWith(Res); SDI->eraseFromParent(); // Try to simplify our new udiv. - processUDivOrURem(BO, LVI); + processUDivOrURem(UDiv, LVI); return true; } diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll b/llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll index ec5de0010a14f..8dfa09d477925 100644 --- a/llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/sdiv.ll @@ -177,8 +177,10 @@ define i32 @test7_pos_neg(i32 %x, i32 %y) { ; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) ; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]] -; CHECK-NEXT: ret i32 [[DIV]] +; CHECK-NEXT: [[Y_NONNEG:%.*]] = sub i32 0, [[Y]] +; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X]], [[Y_NONNEG]] +; CHECK-NEXT: [[DIV1_NEG:%.*]] = sub i32 0, [[DIV1]] +; CHECK-NEXT: ret i32 [[DIV1_NEG]] ; %c0 = icmp sge i32 %x, 0 call void @llvm.assume(i1 %c0) @@ -194,8 +196,10 @@ define i32 @test8_neg_pos(i32 %x, i32 %y) { ; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) ; CHECK-NEXT: [[C1:%.*]] = icmp sge i32 [[Y:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]] -; CHECK-NEXT: ret i32 [[DIV]] +; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i32 0, [[X]] +; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X_NONNEG]], [[Y]] +; CHECK-NEXT: [[DIV1_NEG:%.*]] = sub i32 0, [[DIV1]] +; CHECK-NEXT: ret i32 [[DIV1_NEG]] ; %c0 = icmp sle i32 %x, 0 call void @llvm.assume(i1 %c0) @@ -211,8 +215,10 @@ define i32 @test9_neg_neg(i32 %x, i32 %y) { ; CHECK-NEXT: call void @llvm.assume(i1 [[C0]]) ; CHECK-NEXT: [[C1:%.*]] = icmp sle i32 [[Y:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[C1]]) -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[X]], [[Y]] -; CHECK-NEXT: ret i32 [[DIV]] +; CHECK-NEXT: [[X_NONNEG:%.*]] = sub i32 0, [[X]] +; CHECK-NEXT: [[Y_NONNEG:%.*]] = sub i32 0, [[Y]] +; CHECK-NEXT: [[DIV1:%.*]] = udiv i32 [[X_NONNEG]], [[Y_NONNEG]] +; CHECK-NEXT: ret i32 [[DIV1]] ; %c0 = icmp sle i32 %x, 0 call void @llvm.assume(i1 %c0) From 4b19cccbb5d8d77750da96cef2daefa6c28b0e37 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 18 Jul 2020 15:59:51 +0100 Subject: [PATCH 720/771] [PredicateInfo] Fold PredicateWithCondition into PredicateBase (NFC). Each concrete instance of a predicate has a condition (also noted in the original PredicateBase comment) and to me it seems like there is no clear benefit of having both PredicateBase and PredicateWithCondition and they can be folded together. Reviewers: nikic, efriedma Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D84089 --- .../llvm/Transforms/Utils/PredicateInfo.h | 24 +++++++------------ llvm/lib/Transforms/Scalar/NewGVN.cpp | 6 +---- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/llvm/include/llvm/Transforms/Utils/PredicateInfo.h b/llvm/include/llvm/Transforms/Utils/PredicateInfo.h index 657b97c67a8b3..cdac4142555db 100644 --- a/llvm/include/llvm/Transforms/Utils/PredicateInfo.h +++ b/llvm/include/llvm/Transforms/Utils/PredicateInfo.h @@ -83,37 +83,31 @@ class PredicateBase : public ilist_node { // predicates, this is different to OriginalOp which refers to the initial // operand. Value *RenamedOp; + // The condition associated with this predicate. + Value *Condition; + PredicateBase(const PredicateBase &) = delete; PredicateBase &operator=(const PredicateBase &) = delete; PredicateBase() = delete; virtual ~PredicateBase() = default; - -protected: - PredicateBase(PredicateType PT, Value *Op) : Type(PT), OriginalOp(Op) {} -}; - -class PredicateWithCondition : public PredicateBase { -public: - Value *Condition; static bool classof(const PredicateBase *PB) { return PB->Type == PT_Assume || PB->Type == PT_Branch || PB->Type == PT_Switch; } protected: - PredicateWithCondition(PredicateType PT, Value *Op, Value *Condition) - : PredicateBase(PT, Op), Condition(Condition) {} + PredicateBase(PredicateType PT, Value *Op, Value *Condition) + : Type(PT), OriginalOp(Op), Condition(Condition) {} }; // Provides predicate information for assumes. Since assumes are always true, // we simply provide the assume instruction, so you can tell your relative // position to it. -class PredicateAssume : public PredicateWithCondition { +class PredicateAssume : public PredicateBase { public: IntrinsicInst *AssumeInst; PredicateAssume(Value *Op, IntrinsicInst *AssumeInst, Value *Condition) - : PredicateWithCondition(PT_Assume, Op, Condition), - AssumeInst(AssumeInst) {} + : PredicateBase(PT_Assume, Op, Condition), AssumeInst(AssumeInst) {} PredicateAssume() = delete; static bool classof(const PredicateBase *PB) { return PB->Type == PT_Assume; @@ -123,7 +117,7 @@ class PredicateAssume : public PredicateWithCondition { // Mixin class for edge predicates. The FROM block is the block where the // predicate originates, and the TO block is the block where the predicate is // valid. -class PredicateWithEdge : public PredicateWithCondition { +class PredicateWithEdge : public PredicateBase { public: BasicBlock *From; BasicBlock *To; @@ -135,7 +129,7 @@ class PredicateWithEdge : public PredicateWithCondition { protected: PredicateWithEdge(PredicateType PType, Value *Op, BasicBlock *From, BasicBlock *To, Value *Cond) - : PredicateWithCondition(PType, Op, Cond), From(From), To(To) {} + : PredicateBase(PType, Op, Cond), From(From), To(To) {} }; // Provides predicate information for branches. diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index 0ed1773373a71..45d01cc1b5845 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -1539,12 +1539,8 @@ NewGVN::performSymbolicPredicateInfoEvaluation(Instruction *I) const { LLVM_DEBUG(dbgs() << "Found predicate info from instruction !\n"); - auto *PWC = dyn_cast(PI); - if (!PWC) - return nullptr; - auto *CopyOf = I->getOperand(0); - auto *Cond = PWC->Condition; + auto *Cond = PI->Condition; // If this a copy of the condition, it must be either true or false depending // on the predicate info type and edge. From 3ab0f53ef3c9947288e04ee028818176df8f15b1 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 18 Jul 2020 08:59:05 -0700 Subject: [PATCH 721/771] [DebugInfo] Respect relocations when decoding DW_EH_PE_sdata4 & DW_EH_PE_sdata8 and support R_ARM_REL32 The addresses in llvm-dwarfdump --eh-frame output for object files are closer to readelf -wf output now. --- llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp | 4 ++-- llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 6 +++--- llvm/lib/Object/RelocationResolver.cpp | 14 ++++++++++++-- llvm/test/DebugInfo/AArch64/eh-frame.ll | 3 +-- llvm/test/DebugInfo/PowerPC/eh-frame.ll | 5 ++--- llvm/test/MC/Mips/eh-frame.s | 3 ++- .../llvm-dwarfdump/X86/debug_frame_offset.test | 2 +- .../tools/llvm-objdump/MachO/eh_frame-arm64.test | 2 +- .../tools/llvm-readobj/ELF/AArch64/dwarf-cfi.s | 5 +++-- llvm/test/tools/llvm-readobj/ELF/ARM/dwarf-cfi.s | 5 +++-- 10 files changed, 30 insertions(+), 19 deletions(-) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp index 886fe1dff9769..fa0ceb4bbc01f 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDataExtractor.cpp @@ -104,10 +104,10 @@ DWARFDataExtractor::getEncodedPointer(uint64_t *Offset, uint8_t Encoding, Result = getSigned(Offset, 2); break; case dwarf::DW_EH_PE_sdata4: - Result = getSigned(Offset, 4); + Result = SignExtend64<32>(getRelocatedValue(4, Offset)); break; case dwarf::DW_EH_PE_sdata8: - Result = getSigned(Offset, 8); + Result = getRelocatedValue(8, Offset); break; default: return None; diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index 0a1b75592290c..ba7449baaf7f0 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -521,9 +521,9 @@ Error DWARFDebugFrame::parse(DWARFDataExtractor Data) { "parsing FDE data at 0x%" PRIx64 " failed due to missing CIE", StartOffset); - if (auto Val = Data.getEncodedPointer( - &Offset, Cie->getFDEPointerEncoding(), - EHFrameAddress ? EHFrameAddress + Offset : 0)) { + if (auto Val = + Data.getEncodedPointer(&Offset, Cie->getFDEPointerEncoding(), + EHFrameAddress + Offset)) { InitialLocation = *Val; } if (auto Val = Data.getEncodedPointer( diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp index 919799a25c6f2..83170bbc4e6d9 100644 --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -291,12 +291,22 @@ static uint64_t resolvePPC32(RelocationRef R, uint64_t S, uint64_t A) { } static bool supportsARM(uint64_t Type) { - return Type == ELF::R_ARM_ABS32; + switch (Type) { + case ELF::R_ARM_ABS32: + case ELF::R_ARM_REL32: + return true; + default: + return false; + } } static uint64_t resolveARM(RelocationRef R, uint64_t S, uint64_t A) { - if (R.getType() == ELF::R_ARM_ABS32) + switch (R.getType()) { + case ELF::R_ARM_ABS32: return (S + A) & 0xFFFFFFFF; + case ELF::R_ARM_REL32: + return (S + A - R.getOffset()) & 0xFFFFFFFF; + } llvm_unreachable("Invalid relocation type"); } diff --git a/llvm/test/DebugInfo/AArch64/eh-frame.ll b/llvm/test/DebugInfo/AArch64/eh-frame.ll index 9651159271e55..1becd769d52fc 100644 --- a/llvm/test/DebugInfo/AArch64/eh-frame.ll +++ b/llvm/test/DebugInfo/AArch64/eh-frame.ll @@ -7,8 +7,7 @@ ; CHECK-NOT: warning: ; CHECK: FDE cie=00000000 pc=00000000...00000004 -;; TODO Take relocation into consideration -; CHECK: FDE cie=00000000 pc=00000000...00000004 +; CHECK: FDE cie=00000000 pc=00000004...00000008 define void @foo() { entry: diff --git a/llvm/test/DebugInfo/PowerPC/eh-frame.ll b/llvm/test/DebugInfo/PowerPC/eh-frame.ll index 3a8f7df6b61a9..36b1c272f94cc 100644 --- a/llvm/test/DebugInfo/PowerPC/eh-frame.ll +++ b/llvm/test/DebugInfo/PowerPC/eh-frame.ll @@ -7,8 +7,7 @@ ; PPC-NOT: warning: ; PPC: FDE cie=00000000 pc=00000000...00000004 -;; TODO Take relocation into consideration -; PPC: FDE cie=00000000 pc=00000000...00000004 +; PPC: FDE cie=00000000 pc=00000004...00000008 ; RUN: llc -filetype=obj -mtriple=ppc64 %s -o %t64.o ; RUN: llvm-readobj -r %t64.o | FileCheck %s --check-prefix=PPC64_REL @@ -19,7 +18,7 @@ ; PPC64-NOT: warning: ; PPC64: FDE cie=00000000 pc=00000000...00000010 -; PPC64: FDE cie=00000000 pc=00000000...00000010 +; PPC64: FDE cie=00000000 pc=00000010...00000020 ; RUN: llc -filetype=obj -mtriple=ppc64le -code-model=large %s -o %t64l.o ; RUN: llvm-readobj -r %t64l.o | FileCheck %s --check-prefix=PPC64L_REL diff --git a/llvm/test/MC/Mips/eh-frame.s b/llvm/test/MC/Mips/eh-frame.s index 5be0d709a896c..024b9e6ac4889 100644 --- a/llvm/test/MC/Mips/eh-frame.s +++ b/llvm/test/MC/Mips/eh-frame.s @@ -68,7 +68,8 @@ func: // DWARF32-EMPTY: // DWARF32-NEXT: DW_CFA_def_cfa_register: reg29 // -// DWARF32: 00000014 00000010 00000018 FDE cie=00000000 pc=00000000...00000000 +// DWARF32_ABS: 00000014 00000010 00000018 FDE cie=00000000 pc=00000000...00000000 +// DWARF32_PIC: 00000014 00000010 00000018 FDE cie=00000000 pc=0000001c...0000001c // DWARF32-NEXT: Format: DWARF32 // DWARF32-NEXT: DW_CFA_nop: // DWARF32-NEXT: DW_CFA_nop: diff --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test index 598f80379c38f..27e5dfa622b31 100644 --- a/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test +++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_frame_offset.test @@ -9,7 +9,7 @@ CHECK-NOT: pc RUN: llvm-dwarfdump %p/../../dsymutil/Inputs/basic1.macho.x86_64.o \ RUN: -eh-frame=0x00000018 | FileCheck %s --check-prefix=EH EH: .eh_frame contents: -EH-NEXT: 00000018 00000024 0000001c FDE cie=00000000 pc=fffffffffffffd00...fffffffffffffd24 +EH-NEXT: 00000018 00000024 0000001c FDE cie=00000000 pc=fffffffffffffd20...fffffffffffffd44 EH-NEXT: Format: DWARF32 EH-NEXT: DW_CFA_advance_loc: 1 EH-NOT: pc diff --git a/llvm/test/tools/llvm-objdump/MachO/eh_frame-arm64.test b/llvm/test/tools/llvm-objdump/MachO/eh_frame-arm64.test index 1768d019597a5..31f87a5035e7e 100644 --- a/llvm/test/tools/llvm-objdump/MachO/eh_frame-arm64.test +++ b/llvm/test/tools/llvm-objdump/MachO/eh_frame-arm64.test @@ -12,7 +12,7 @@ # CHECK: DW_CFA_def_cfa: reg31 +0 -# CHECK: 00000014 00000020 00000018 FDE cie=00000000 pc=ffffffffffffffe4...00000004 +# CHECK: 00000014 00000020 00000018 FDE cie=00000000 pc=00000000...00000020 # CHECK: DW_CFA_advance_loc: 8 # CHECK: DW_CFA_def_cfa_offset: +16 # CHECK: DW_CFA_offset: reg30 -8 diff --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/dwarf-cfi.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/dwarf-cfi.s index f129546787602..cefc00171544e 100644 --- a/llvm/test/tools/llvm-readobj/ELF/AArch64/dwarf-cfi.s +++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/dwarf-cfi.s @@ -10,9 +10,10 @@ # CHECK: Program: # CHECK-NEXT: DW_CFA_def_cfa: reg31 +0 +## FIXME Use getEHFrameSection() so that the address is decoded correctly. # CHECK: [0x14] FDE length=16 cie=[0x0] -# CHECK-NEXT: initial_location: 0x0 -# CHECK-NEXT: address_range: 0x4 (end : 0x4) +# CHECK-NEXT: initial_location: 0x1c +# CHECK-NEXT: address_range: 0x4 (end : 0x20) # CHECK: Program: # CHECK-NEXT: DW_CFA_nop: diff --git a/llvm/test/tools/llvm-readobj/ELF/ARM/dwarf-cfi.s b/llvm/test/tools/llvm-readobj/ELF/ARM/dwarf-cfi.s index 36d71d61c9f0a..227ac263b4c6b 100644 --- a/llvm/test/tools/llvm-readobj/ELF/ARM/dwarf-cfi.s +++ b/llvm/test/tools/llvm-readobj/ELF/ARM/dwarf-cfi.s @@ -10,9 +10,10 @@ # CHECK: Program: # CHECK-NEXT: DW_CFA_def_cfa: reg13 +0 +## FIXME Use getEHFrameSection() so that the address is decoded correctly. # CHECK: [0x14] FDE length=16 cie=[0x0] -# CHECK-NEXT: initial_location: 0x0 -# CHECK-NEXT: address_range: 0x4 (end : 0x4) +# CHECK-NEXT: initial_location: 0x1c +# CHECK-NEXT: address_range: 0x4 (end : 0x20) # CHECK: Program: # CHECK-NEXT: DW_CFA_nop: From 6d7ec54170f9ef68710f484299caa1a6dd42ff48 Mon Sep 17 00:00:00 2001 From: Anders Waldenborg Date: Sat, 18 Jul 2020 17:26:06 +0200 Subject: [PATCH 722/771] [clang-format] Make sure rst documentation matches comments clang/docs/tools/dump_format_style.py is used to read the comments from clang/include/clang/Format/Format.h and update the contents of clang/docs/ClangFormatStyleOptions.rst Recent changes made these out of date. This commit syncs them by folding the improved wording back to the comments and then regenerating the rst file. Differential Revision: https://reviews.llvm.org/D84103 --- clang/docs/ClangFormatStyleOptions.rst | 9 +++++---- clang/include/clang/Format/Format.h | 11 ++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index e84676760c300..6647b117ac596 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2694,8 +2694,11 @@ the configuration (without a prefix: ``Auto``). Use tabs whenever we need to fill whitespace that spans at least from one tab stop to the next one. + + **WhitespaceSensitiveMacros** (``std::vector``) - A vector of macros which are whitespace-sensitive and should not be touched. + A vector of macros which are whitespace-sensitive and should not + be touched. These are expected to be macros of the form: @@ -2709,9 +2712,7 @@ the configuration (without a prefix: ``Auto``). WhitespaceSensitiveMacros: ['STRINGIZE', 'PP_STRINGIZE'] - For example: BOOST_PP_STRINGIZE. - - + For example: BOOST_PP_STRINGIZE .. END_FORMAT_STYLE_OPTIONS diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 3549ec9eee0e5..7201c11f1158e 100755 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -1425,15 +1425,20 @@ struct FormatStyle { /// For example: TESTSUITE std::vector NamespaceMacros; - /// A vector of macros which are whitespace-sensitive and shouldn't be - /// touched. + /// A vector of macros which are whitespace-sensitive and should not + /// be touched. /// /// These are expected to be macros of the form: /// \code /// STRINGIZE(...) /// \endcode /// - /// For example: STRINGIZE + /// In the .clang-format configuration file, this can be configured like: + /// \code{.yaml} + /// WhitespaceSensitiveMacros: ['STRINGIZE', 'PP_STRINGIZE'] + /// \endcode + /// + /// For example: BOOST_PP_STRINGIZE std::vector WhitespaceSensitiveMacros; tooling::IncludeStyle IncludeStyle; From 7099a4b56bebf44158d413ddb2b4879e9060f9ce Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 18 Jul 2020 09:07:40 -0700 Subject: [PATCH 723/771] [ELF][test] Update test after DW_EH_PE_sdata4/DW_EH_PE_sdata8 change --- lld/test/ELF/eh-frame-hdr-augmentation.s | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lld/test/ELF/eh-frame-hdr-augmentation.s b/lld/test/ELF/eh-frame-hdr-augmentation.s index dbec54a1a8a22..9c9b862ae80d5 100644 --- a/lld/test/ELF/eh-frame-hdr-augmentation.s +++ b/lld/test/ELF/eh-frame-hdr-augmentation.s @@ -20,7 +20,8 @@ // CHECK-NEXT: DW_CFA_nop: // CHECK-NEXT: DW_CFA_nop: -// CHECK: 00000020 00000014 00000024 FDE cie=00000000 pc=00001014...00001014 +/// FIXME Handle relocation correctly +// CHECK: 00000020 00000014 00000024 FDE cie=00000000 pc=0000103c...0000103c // CHECK-NEXT: Format: DWARF32 // CHECK-NEXT: LSDA Address: 000000000000100b // CHECK-NEXT: DW_CFA_nop: From 9548697df9c6f65a3dba4e8de4d015650e73101c Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sat, 18 Jul 2020 16:12:41 +0000 Subject: [PATCH 724/771] Fix Markdown format for lists in the Standard Dialect documentation This affects the rendering on the website. --- .../mlir/Dialect/StandardOps/IR/Ops.td | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td index c3e3ada8cd40e..1b525455dd8dc 100644 --- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td +++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td @@ -2567,15 +2567,16 @@ def SubViewOp : Std_Op<"subview", [ the operation's offsets, sizes and strides arguments. The SubView operation supports the following arguments: - *) Memref: the "base" memref on which to create a "view" memref. - *) Offsets: memref-rank number of dynamic offsets or static integer - attributes into the "base" memref at which to create the "view" - memref. - *) Sizes: memref-rank number of dynamic sizes or static integer attributes - which specify the sizes of the result "view" memref type. - *) Strides: memref-rank number of dynamic strides or static integer - attributes multiplicatively to the base memref strides in each - dimension. + + * Memref: the "base" memref on which to create a "view" memref. + * Offsets: memref-rank number of dynamic offsets or static integer + attributes into the "base" memref at which to create the "view" + memref. + * Sizes: memref-rank number of dynamic sizes or static integer attributes + which specify the sizes of the result "view" memref type. + * Strides: memref-rank number of dynamic strides or static integer + attributes multiplicatively to the base memref strides in each + dimension. Example 1: @@ -3129,21 +3130,23 @@ def ViewOp : Std_Op<"view", [ The "view" operation extracts an N-D contiguous memref with empty layout map with arbitrary element type from a 1-D contiguous memref with empty layout map of i8 element type. The ViewOp supports the following arguments: - *) A single dynamic byte-shift operand must be specified which represents a - a shift of the base 1-D memref pointer from which to create the resulting - contiguous memref view with identity layout. - *) A dynamic size operand that must be specified for each dynamic dimension - in the resulting view memref type. + + * A single dynamic byte-shift operand must be specified which represents a + a shift of the base 1-D memref pointer from which to create the resulting + contiguous memref view with identity layout. + * A dynamic size operand that must be specified for each dynamic dimension + in the resulting view memref type. The "view" operation gives a structured indexing form to a flat 1-D buffer. Unlike "subview" it can perform a type change. The type change behavior requires the op to have special semantics because, e.g. a byte shift of 3 cannot be represented as an offset on f64. For now, a "view" op: - 1) Only takes a contiguous source memref with 0 offset and empty layout. - 2) Must specify a byte_shift operand (in the future, a special integer - attribute may be added to support the folded case). - 3) Returns a contiguous memref with 0 offset and empty layout. + + 1. Only takes a contiguous source memref with 0 offset and empty layout. + 2. Must specify a byte_shift operand (in the future, a special integer + attribute may be added to support the folded case). + 3. Returns a contiguous memref with 0 offset and empty layout. Example: From 570a3977de9253bd93171ebd456bfd345d08e4eb Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sat, 18 Jul 2020 16:22:31 +0000 Subject: [PATCH 725/771] Fix dead link on MLIR website --- mlir/include/mlir/Dialect/StandardOps/IR/Ops.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td index 1b525455dd8dc..cde317065ffee 100644 --- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td +++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td @@ -1700,7 +1700,7 @@ def LoadOp : Std_Op<"load", In an `affine.if` or `affine.for` body, the indices of a load are restricted to SSA values bound to surrounding loop induction variables, - [symbols](../Affine.md#dimensions-and-symbols), results of a + [symbols](AffineOps.md#dimensions-and-symbols), results of a [`constant` operation](#stdconstant-constantop), or the result of an `affine.apply` operation that can in turn take as arguments all of the aforementioned SSA values or the recursively result of such an From 9dceb32f300d021bf6ace6d27ffaf670799e2e8d Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 18 Jul 2020 19:41:21 +0300 Subject: [PATCH 726/771] [NFC][CVP] processSDiv(): pacify gcc compilers --- .../Transforms/Scalar/CorrelatedValuePropagation.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp index fb7a005708e56..48968166c605f 100644 --- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp +++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp @@ -697,14 +697,14 @@ static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) { struct Operand { Value *V; - Domain Domain; + Domain D; }; std::array Ops; - for (const auto &I : zip(Ops, SDI->operands())) { + for (const auto I : zip(Ops, SDI->operands())) { Operand &Op = std::get<0>(I); Op.V = std::get<1>(I); - Op.Domain = getDomain(Op.V); - if (Op.Domain == Domain::Unknown) + Op.D = getDomain(Op.V); + if (Op.D == Domain::Unknown) return false; } @@ -713,7 +713,7 @@ static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) { // We need operands to be non-negative, so negate each one that isn't. for (Operand &Op : Ops) { - if (Op.Domain == Domain::NonNegative) + if (Op.D == Domain::NonNegative) continue; auto *BO = BinaryOperator::CreateNeg(Op.V, Op.V->getName() + ".nonneg", SDI); @@ -729,7 +729,7 @@ static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) { Value *Res = UDiv; // If the operands had two different domains, we need to negate the result. - if (Ops[0].Domain != Ops[1].Domain) + if (Ops[0].D != Ops[1].D) Res = BinaryOperator::CreateNeg(Res, Res->getName() + ".neg", SDI); SDI->replaceAllUsesWith(Res); From 3bbbe4c4b6c8e20538a388df164da6f8d935e0cc Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Sat, 18 Jul 2020 12:00:08 -0400 Subject: [PATCH 727/771] [OpenMP] Add Additional Function Attribute Information to OMPKinds.def Summary: This patch adds more function attribute information to the runtime function definitions in OMPKinds.def. The goal is to provide sufficient information about OpenMP runtime functions to perform more optimizations on OpenMP code. Reviewers: jdoerfert Subscribers: aaron.ballman cfe-commits yaxunl guansong sstefan1 llvm-commits Tags: #OpenMP #clang #LLVM Differential Revision: https://reviews.llvm.org/D81031 --- clang/test/OpenMP/barrier_codegen.cpp | 2 +- .../include/llvm/Frontend/OpenMP/OMPKinds.def | 675 +++++++++------- llvm/test/Transforms/OpenMP/add_attributes.ll | 745 ++++++++++++------ .../Transforms/OpenMP/parallel_deletion.ll | 2 +- 4 files changed, 903 insertions(+), 521 deletions(-) diff --git a/clang/test/OpenMP/barrier_codegen.cpp b/clang/test/OpenMP/barrier_codegen.cpp index f84a26380df9e..35b2ed7212761 100644 --- a/clang/test/OpenMP/barrier_codegen.cpp +++ b/clang/test/OpenMP/barrier_codegen.cpp @@ -46,7 +46,7 @@ int main(int argc, char **argv) { // IRBUILDER: ; Function Attrs: nounwind // IRBUILDER-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) # // IRBUILDER_OPT: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly -// IRBUILDER_OPT-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) # +// IRBUILDER_OPT-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t* nocapture nofree readonly) # // CHECK: define {{.+}} [[TMAIN_INT]]( // CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num([[IDENT_T]]* [[LOC]]) diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index 0dc2b34f2e4d6..4f2fcb8af5d1d 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -383,7 +383,8 @@ __OMP_RTL(__kmpc_push_proc_bind, false, Void, IdentPtr, Int32, /* Int */ Int32) __OMP_RTL(__kmpc_serialized_parallel, false, Void, IdentPtr, Int32) __OMP_RTL(__kmpc_end_serialized_parallel, false, Void, IdentPtr, Int32) __OMP_RTL(__kmpc_omp_reg_task_with_affinity, false, Int32, IdentPtr, Int32, - Int8Ptr, Int32, Int8Ptr) + /* kmp_task_t */ VoidPtr, Int32, + /* kmp_task_affinity_info_t */ VoidPtr) __OMP_RTL(omp_get_thread_num, false, Int32, ) __OMP_RTL(omp_get_num_threads, false, Int32, ) @@ -430,8 +431,7 @@ __OMP_RTL(__kmpc_reduce, false, Int32, IdentPtr, Int32, Int32, SizeTy, VoidPtr, ReduceFunctionPtr, KmpCriticalNamePtrTy) __OMP_RTL(__kmpc_reduce_nowait, false, Int32, IdentPtr, Int32, Int32, SizeTy, VoidPtr, ReduceFunctionPtr, KmpCriticalNamePtrTy) -__OMP_RTL(__kmpc_end_reduce, false, Void, IdentPtr, Int32, - KmpCriticalNamePtrTy) +__OMP_RTL(__kmpc_end_reduce, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy) __OMP_RTL(__kmpc_end_reduce_nowait, false, Void, IdentPtr, Int32, KmpCriticalNamePtrTy) @@ -514,10 +514,10 @@ __OMP_RTL(__kmpc_taskloop, false, Void, IdentPtr, /* Int */ Int32, VoidPtr, /* Int */ Int32, Int64, VoidPtr) __OMP_RTL(__kmpc_omp_target_task_alloc, false, /* kmp_task_t */ VoidPtr, IdentPtr, Int32, Int32, SizeTy, SizeTy, TaskRoutineEntryPtr, Int64) -__OMP_RTL(__kmpc_taskred_modifier_init, false, VoidPtr, IdentPtr, - /* Int */ Int32, /* Int */ Int32, /* Int */ Int32, VoidPtr) -__OMP_RTL(__kmpc_taskred_init, false, VoidPtr, /* Int */ Int32, - /* Int */ Int32, VoidPtr) +__OMP_RTL(__kmpc_taskred_modifier_init, false, /* kmp_taskgroup */ VoidPtr, + IdentPtr, /* Int */ Int32, /* Int */ Int32, /* Int */ Int32, VoidPtr) +__OMP_RTL(__kmpc_taskred_init, false, /* kmp_taskgroup */ VoidPtr, + /* Int */ Int32, /* Int */ Int32, VoidPtr) __OMP_RTL(__kmpc_task_reduction_modifier_fini, false, Void, IdentPtr, /* Int */ Int32, /* Int */ Int32) __OMP_RTL(__kmpc_task_reduction_get_th_data, false, VoidPtr, Int32, VoidPtr, @@ -594,7 +594,9 @@ __OMP_RTL(__last, false, Void, ) #undef __OMP_RTL #undef OMP_RTL +#define ParamAttrs(...) ArrayRef({__VA_ARGS__}) #define EnumAttr(Kind) Attribute::get(Ctx, Attribute::AttrKind::Kind) +#define EnumAttrInt(Kind, N) Attribute::get(Ctx, Attribute::AttrKind::Kind, N) #define AttributeSet(...) \ AttributeSet::get(Ctx, ArrayRef({__VA_ARGS__})) @@ -607,19 +609,94 @@ __OMP_RTL(__last, false, Void, ) __OMP_ATTRS_SET(GetterAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(ReadOnly), - EnumAttr(NoSync), EnumAttr(NoFree), EnumAttr(InaccessibleMemOnly)) + EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(InaccessibleMemOnly), + EnumAttr(WillReturn)) : AttributeSet(EnumAttr(NoUnwind))) __OMP_ATTRS_SET(GetterArgWriteAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), - EnumAttr(NoFree), EnumAttr(InaccessibleMemOrArgMemOnly)) + EnumAttr(NoFree), + EnumAttr(InaccessibleMemOrArgMemOnly), + EnumAttr(WillReturn)) : AttributeSet(EnumAttr(NoUnwind))) __OMP_ATTRS_SET(SetterAttrs, OptimisticAttributes ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(WriteOnly), - EnumAttr(NoSync), EnumAttr(NoFree), EnumAttr(InaccessibleMemOnly)) + EnumAttr(NoSync), EnumAttr(NoFree), + EnumAttr(InaccessibleMemOnly), + EnumAttr(WillReturn)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(DefaultAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), + EnumAttr(WillReturn), EnumAttr(NoFree)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(BarrierAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind)) : AttributeSet(EnumAttr(NoUnwind))) +__OMP_ATTRS_SET(InaccessibleArgOnlyAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), + EnumAttr(InaccessibleMemOrArgMemOnly), + EnumAttr(WillReturn), EnumAttr(NoFree)) + : AttributeSet(EnumAttr(NoUnwind))) + +#if 0 +__OMP_ATTRS_SET(InaccessibleOnlyAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), + EnumAttr(InaccessibleMemOnly), + EnumAttr(WillReturn), EnumAttr(NoFree)) + : AttributeSet(EnumAttr(NoUnwind))) +#endif + +__OMP_ATTRS_SET(AllocAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind), EnumAttr(NoSync), + EnumAttr(WillReturn)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(ForkAttrs, OptimisticAttributes + ? AttributeSet(EnumAttr(NoUnwind)) + : AttributeSet(EnumAttr(NoUnwind))) + +__OMP_ATTRS_SET(ReadOnlyPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(ReadOnly), EnumAttr(NoFree), + EnumAttr(NoCapture)) + : AttributeSet()) + +#if 0 +__OMP_ATTRS_SET(WriteOnlyPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(WriteOnly), EnumAttr(NoFree), + EnumAttr(NoCapture)) + : AttributeSet()) +#endif + +__OMP_ATTRS_SET(ArgPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoCapture), EnumAttr(NoFree)) + : AttributeSet()) + +__OMP_ATTRS_SET(ReturnPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoAlias)) + : AttributeSet()) + +#if 0 +__OMP_ATTRS_SET(ReturnAlignedPtrAttrs, + OptimisticAttributes + ? AttributeSet(EnumAttr(NoAlias), EnumAttrInt(Alignment, 8), + EnumAttrInt(DereferenceableOrNull, 8)) + : AttributeSet()) +#endif + #undef __OMP_ATTRS_SET #undef OMP_ATTRS_SET @@ -630,295 +707,309 @@ __OMP_ATTRS_SET(SetterAttrs, #define __OMP_RTL_ATTRS(Name, FnAttrSet, RetAttrSet, ArgAttrSets) \ OMP_RTL_ATTRS(OMPRTL_##Name, FnAttrSet, RetAttrSet, ArgAttrSets) -__OMP_RTL_ATTRS(__kmpc_barrier, AttributeSet(), AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_cancel, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_cancel_barrier, AttributeSet(), AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_flush, AttributeSet(), AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_global_thread_num, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_fork_call, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_taskwait, AttributeSet(), AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_taskyield, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_push_num_threads, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_push_proc_bind, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_serialized_parallel, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_serialized_parallel, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(omp_get_thread_num, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_num_threads, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_max_threads, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_in_parallel, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_dynamic, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_cancellation, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_nested, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_schedule, GetterArgWriteAttrs, AttributeSet(), - ArrayRef( - {AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)), - AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly))})) -__OMP_RTL_ATTRS(omp_get_thread_limit, GetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_barrier, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_cancel, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_cancel_barrier, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_flush, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_global_thread_num, GetterAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_fork_call, ForkAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_taskwait, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_taskyield, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_push_num_threads, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_push_proc_bind, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_serialized_parallel, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end_serialized_parallel, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_reg_task_with_affinity, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs, + AttributeSet(), ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(omp_get_thread_num, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_num_threads, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_max_threads, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_in_parallel, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_dynamic, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_cancellation, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_nested, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS( + omp_get_schedule, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)), + AttributeSet(EnumAttr(NoCapture), EnumAttr(WriteOnly)))) +__OMP_RTL_ATTRS(omp_get_thread_limit, GetterAttrs, AttributeSet(), ParamAttrs()) __OMP_RTL_ATTRS(omp_get_supported_active_levels, GetterAttrs, AttributeSet(), - {}) -__OMP_RTL_ATTRS(omp_get_max_active_levels, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_level, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_ancestor_thread_num, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_team_size, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_active_level, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_in_final, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_proc_bind, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_num_places, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_num_procs, GetterAttrs, AttributeSet(), {}) + ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_max_active_levels, GetterAttrs, AttributeSet(), + ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_level, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_ancestor_thread_num, GetterAttrs, AttributeSet(), + ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_team_size, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_active_level, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_in_final, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_proc_bind, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_num_places, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_num_procs, GetterAttrs, AttributeSet(), ParamAttrs()) __OMP_RTL_ATTRS(omp_get_place_proc_ids, GetterArgWriteAttrs, AttributeSet(), - ArrayRef({AttributeSet(), - AttributeSet(EnumAttr(NoCapture), - EnumAttr(WriteOnly))})) -__OMP_RTL_ATTRS(omp_get_place_num, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_partition_num_places, GetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_get_partition_place_nums, GetterAttrs, AttributeSet(), {}) - -__OMP_RTL_ATTRS(omp_set_num_threads, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_set_dynamic, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_set_nested, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_set_schedule, SetterAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(omp_set_max_active_levels, SetterAttrs, AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_master, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_master, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_critical, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_critical_with_hint, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_critical, - AttributeSet(EnumAttr(InaccessibleMemOrArgMemOnly)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_begin, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_reduce, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_reduce_nowait, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_reduce, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_reduce_nowait, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_ordered, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_ordered, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_for_static_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_for_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_for_static_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_for_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_for_static_fini, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_next_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_team_static_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_team_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_team_static_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_team_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8u, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_single, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_single, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_omp_task_alloc, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_task, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_end_taskgroup, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_taskgroup, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_task_begin_if0, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_task_complete_if0, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_task_with_deps, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_taskloop, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_omp_target_task_alloc, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_taskred_modifier_init, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_taskred_init, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_fini, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_reduction_get_th_data, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_reduction_init, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_init, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_proxy_task_completed_ooo, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_omp_wait_deps, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_cancellationpoint, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_fork_teams, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_push_num_teams, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_copyprivate, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_threadprivate_cached, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_threadprivate_register, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_doacross_init, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_doacross_post, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_doacross_wait, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_doacross_fini, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_alloc, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_free, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_init_allocator, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_destroy_allocator, AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) - -__OMP_RTL_ATTRS(__kmpc_push_target_tripcount, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_teams_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_teams_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_register_requires, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_begin_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_begin_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_end_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_end_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_update_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_target_data_update_nowait_mapper, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_mapper_num_components, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__tgt_push_mapper_component, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_task_allow_completion_event, - AttributeSet(EnumAttr(NoUnwind)), - AttributeSet(), {}) + ParamAttrs(AttributeSet(), AttributeSet(EnumAttr(NoCapture), + EnumAttr(WriteOnly)))) +__OMP_RTL_ATTRS(omp_get_place_num, GetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_partition_num_places, GetterAttrs, AttributeSet(), + ParamAttrs()) +__OMP_RTL_ATTRS(omp_get_partition_place_nums, GetterAttrs, AttributeSet(), + ParamAttrs()) + +__OMP_RTL_ATTRS(omp_set_num_threads, SetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_set_dynamic, SetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_set_nested, SetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_set_schedule, SetterAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(omp_set_max_active_levels, SetterAttrs, AttributeSet(), + ParamAttrs()) + +__OMP_RTL_ATTRS(__kmpc_master, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end_master, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_critical, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_critical_with_hint, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_end_critical, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) + +__OMP_RTL_ATTRS(__kmpc_begin, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_reduce, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), ReadOnlyPtrAttrs, AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_reduce_nowait, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), ReadOnlyPtrAttrs, AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_end_reduce, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_end_reduce_nowait, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) + +__OMP_RTL_ATTRS(__kmpc_ordered, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end_ordered, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_for_static_init_4, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_for_static_init_4u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_for_static_init_8, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_for_static_init_8u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_for_static_fini, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_4u, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_dispatch_init_8u, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_4, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_4u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_8, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_init_8u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_4, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_4u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_8, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_next_8u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_4u, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dispatch_fini_8u, InaccessibleArgOnlyAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_team_static_init_4, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_team_static_init_4u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_team_static_init_8, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_team_static_init_8u, GetterArgWriteAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ArgPtrAttrs, + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_4u, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + ArgPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_dist_for_static_init_8u, GetterArgWriteAttrs, + AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, ArgPtrAttrs, + ArgPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_single, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_end_single, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_omp_task_alloc, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_task, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_end_taskgroup, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_taskgroup, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_task_begin_if0, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_task_complete_if0, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_omp_task_with_deps, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), ReadOnlyPtrAttrs, AttributeSet(), + ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_taskloop, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), ArgPtrAttrs, ArgPtrAttrs, + AttributeSet(), AttributeSet(), AttributeSet(), + AttributeSet(), AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_omp_target_task_alloc, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + AttributeSet(), AttributeSet(), ReadOnlyPtrAttrs, + AttributeSet())) +__OMP_RTL_ATTRS(__kmpc_taskred_modifier_init, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_taskred_init, DefaultAttrs, AttributeSet(), ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_fini, BarrierAttrs, + AttributeSet(), ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_task_reduction_get_th_data, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_task_reduction_init, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_task_reduction_modifier_init, DefaultAttrs, + ReturnPtrAttrs, ParamAttrs()) +__OMP_RTL_ATTRS(__kmpc_proxy_task_completed_ooo, DefaultAttrs, AttributeSet(), + ParamAttrs()) + +__OMP_RTL_ATTRS(__kmpc_omp_wait_deps, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_cancellationpoint, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_fork_teams, ForkAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_push_num_teams, InaccessibleArgOnlyAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_copyprivate, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), AttributeSet(), + ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_threadprivate_cached, DefaultAttrs, ReturnPtrAttrs, + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_threadprivate_register, DefaultAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs, + ReadOnlyPtrAttrs, ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_doacross_init, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_doacross_post, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_doacross_wait, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs, AttributeSet(), ReadOnlyPtrAttrs)) +__OMP_RTL_ATTRS(__kmpc_doacross_fini, BarrierAttrs, AttributeSet(), + ParamAttrs(ReadOnlyPtrAttrs)) + +__OMP_RTL_ATTRS(__kmpc_alloc, DefaultAttrs, ReturnPtrAttrs, {}) +__OMP_RTL_ATTRS(__kmpc_free, AllocAttrs, AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_init_allocator, DefaultAttrs, ReturnPtrAttrs, {}) +__OMP_RTL_ATTRS(__kmpc_destroy_allocator, AllocAttrs, AttributeSet(), {}) + +__OMP_RTL_ATTRS(__kmpc_push_target_tripcount, SetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_nowait_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_teams_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_teams_nowait_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_register_requires, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_begin_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_begin_nowait_mapper, ForkAttrs, + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_end_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_end_nowait_mapper, ForkAttrs, + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_update_mapper, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_target_data_update_nowait_mapper, ForkAttrs, + AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_mapper_num_components, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__tgt_push_mapper_component, ForkAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_task_allow_completion_event, DefaultAttrs, + ReturnPtrAttrs, ParamAttrs(ReadOnlyPtrAttrs)) #undef __OMP_RTL_ATTRS #undef OMP_RTL_ATTRS #undef AttributeSet #undef EnumAttr +#undef EnumAttrInt +#undef ParamAttrs ///} diff --git a/llvm/test/Transforms/OpenMP/add_attributes.ll b/llvm/test/Transforms/OpenMP/add_attributes.ll index 6e10613ed43c3..e92447d79feac 100644 --- a/llvm/test/Transforms/OpenMP/add_attributes.ll +++ b/llvm/test/Transforms/OpenMP/add_attributes.ll @@ -890,373 +890,373 @@ declare void @__kmpc_proxy_task_completed_ooo(i8*) ; CHECK: ; Function Attrs: nounwind ; CHECK-NEXT: declare dso_local i32 @omp_get_supported_active_levels() #0 -; CHECK-NOT: Function Attrs -; CHECK: declare void @__kmpc_barrier(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_barrier(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) #0 -; CHECK-NOT: Function Attrs -; CHECK: declare i32 @__kmpc_cancel_barrier(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_cancel_barrier(%struct.ident_t*, i32) #0 -; CHECK-NOT: Function Attrs -; CHECK: declare void @__kmpc_flush(%struct.ident_t*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_flush(%struct.ident_t*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) #0 -; CHECK-NOT: Function Attrs -; CHECK: declare i32 @__kmpc_omp_taskwait(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_taskwait(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare i32 @__kmpc_master(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_master(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_end_master(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_master(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_critical(%struct.ident_t*, i32, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_critical(%struct.ident_t*, i32, [8 x i32]*) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t*, i32, [8 x i32]*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t*, i32, [8 x i32]*, i32) #0 -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly -; CHECK-NEXT: declare void @__kmpc_end_critical(%struct.ident_t*, i32, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_critical(%struct.ident_t*, i32, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_begin(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_begin(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end(%struct.ident_t*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end(%struct.ident_t*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t*, i32, i32, i64, i8*, void (i8*, i8*)*, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t*, i32, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t*, i32, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t*, i32, [8 x i32]*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t*, i32, [8 x i32]*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_ordered(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_ordered(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t*, i32, i32, i32*, i32*, i32*, i32*, i32*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t*, i32, i32, i32*, i64*, i64*, i64*, i64*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_single(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_single(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_single(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_single(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_omp_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_omp_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t*, i32, i32, i32*, i32, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t*, i32, i32, i32*, i64, i64, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t*, i32, i32, i32, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t*, i32, i32, i32, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t*, i32, i32, i32, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t*, i32, i32, i32, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t*, i32, i32, i64, i64, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t*, i32, i32, i64, i64, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t*, i32, i32, i64, i64, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t*, i32, i32, i64, i64, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t*, i32, i32*, i32*, i32*, i32*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t*, i32, i32*, i64*, i64*, i64*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t*, i32, i8*, i32, i8*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t*, i32, i8*, i32, i8*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t*, i32, i32, i8*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t*, i32, i32, i8*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t*, i32, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t*, i32, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_taskloop(%struct.ident_t*, i32, i8*, i32, i64*, i64*, i64, i32, i32, i64, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_taskloop(%struct.ident_t*, i32, i8*, i32, i64*, i64*, i64, i32, i32, i64, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_omp_target_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_omp_target_task_alloc(%struct.ident_t*, i32, i32, i64, i64, i32 (i32, i8*)*, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_taskred_modifier_init(%struct.ident_t*, i32, i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_taskred_modifier_init(%struct.ident_t*, i32, i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t*, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t*, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t*, i32, i64, i8*, void (i8*, i8*)*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t*, i32, i64, i8*, void (i8*, i8*)*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_threadprivate_cached(%struct.ident_t*, i32, i8*, i64, i8***) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_threadprivate_cached(%struct.ident_t*, i32, i8*, i64, i8***) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t*, i8*, i8* (i8*)*, i8* (i8*, i8*)*, void (i8*)*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t*, i8*, i8* (i8*)*, i8* (i8*, i8*)*, void (i8*)*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t*, i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t*, i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t*, i32, i64*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t*, i32, i64*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t*, i32, i64*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t*, i32, i64*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t*, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t*, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_alloc(i32, i64, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_alloc(i32, i64, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_free(i32, i8*, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_free(i32, i8*, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_register_requires(i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_register_requires(i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i64 @__tgt_mapper_num_components(i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i64 @__tgt_mapper_num_components(i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_allow_completion_event(%struct.ident_t*, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_allow_completion_event(%struct.ident_t*, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_init(i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_init(i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) #0 -; CHECK: Function Attrs: nounwind -; CHECK-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) +; CHECK: ; Function Attrs: nounwind +; CHECK-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) #0 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_num_threads(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_dynamic(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_nested(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_max_active_levels(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind writeonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly ; OPTIMISTIC-NEXT: declare dso_local void @omp_set_schedule(i32, i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_num_threads() #1 ; OPTIMISTIC-NOT: Function Attrs ; OPTIMISTIC: declare dso_local void @use_int(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_dynamic() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_nested() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_max_threads() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_thread_num() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_num_procs() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_in_parallel() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_in_final() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_active_level() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_level() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_ancestor_thread_num(i32) #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_team_size(i32) #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_thread_limit() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_max_active_levels() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn ; OPTIMISTIC-NEXT: declare dso_local void @omp_get_schedule(i32* nocapture writeonly, i32* nocapture writeonly) #2 ; OPTIMISTIC-NOT: Function Attrs @@ -1418,8 +1418,299 @@ declare void @__kmpc_proxy_task_completed_ooo(i8*) ; OPTIMISTIC-NOT: Function Attrs ; OPTIMISTIC: declare dso_local i32 @omp_pause_resource_all(i32) -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn ; OPTIMISTIC-NEXT: declare dso_local i32 @omp_get_supported_active_levels() #1 -; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly -; OPTIMISTIC-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t*) +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind readonly willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_global_thread_num(%struct.ident_t* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_fork_call(%struct.ident_t* nocapture nofree readonly, i32, void (i32*, i32*, ...)* nocapture nofree readonly, ...) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_taskwait(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_taskyield(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_push_num_threads(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_push_proc_bind(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_serialized_parallel(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_end_serialized_parallel(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_master(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_end_master(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_critical(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_critical_with_hint(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_critical(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_begin(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_end(%struct.ident_t* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__kmpc_reduce(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__kmpc_reduce_nowait(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_reduce(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_reduce_nowait(%struct.ident_t* nocapture nofree readonly, i32, [8 x i32]*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_ordered(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_ordered(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_for_static_fini(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_team_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_for_static_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64, i64) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__kmpc_single(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_single(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_omp_task_alloc(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i32 (i32, i8*)* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_task(%struct.ident_t* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_end_taskgroup(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_taskgroup(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i32, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64, i64, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dist_dispatch_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32* nocapture nofree, i64, i64, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_4(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_4u(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_8(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_init_8u(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i64, i64) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_4(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_4u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree, i32* nocapture nofree) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_8(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_dispatch_next_8u(%struct.ident_t* nocapture nofree readonly, i32, i32* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree, i64* nocapture nofree) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_4(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_4u(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_8(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_dispatch_fini_8u(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_omp_task_begin_if0(%struct.ident_t* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_omp_task_complete_if0(%struct.ident_t* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_omp_task_with_deps(%struct.ident_t* nocapture nofree readonly, i32, i8*, i32, i8* nocapture nofree readonly, i32, i8* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_omp_wait_deps(%struct.ident_t* nocapture nofree readonly, i32, i32, i8* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i32 @__kmpc_cancellationpoint(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: inaccessiblemem_or_argmemonly nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_push_num_teams(%struct.ident_t* nocapture nofree readonly, i32, i32, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_fork_teams(%struct.ident_t* nocapture nofree readonly, i32, void (i32*, i32*, ...)* nocapture nofree readonly, ...) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_taskloop(%struct.ident_t* nocapture nofree readonly, i32, i8*, i32, i64* nocapture nofree, i64* nocapture nofree, i64, i32, i32, i64, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_omp_target_task_alloc(%struct.ident_t* nocapture nofree readonly, i32, i32, i64, i64, i32 (i32, i8*)* nocapture nofree readonly, i64) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_taskred_modifier_init(%struct.ident_t* nocapture nofree readonly, i32, i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare i8* @__kmpc_taskred_init(i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_task_reduction_modifier_fini(%struct.ident_t* nocapture nofree readonly, i32, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_copyprivate(%struct.ident_t* nocapture nofree readonly, i32, i64, i8* nocapture nofree readonly, void (i8*, i8*)*, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_threadprivate_cached(%struct.ident_t* nocapture nofree readonly, i32, i8*, i64, i8***) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_threadprivate_register(%struct.ident_t* nocapture nofree readonly, i8*, i8* (i8*)* nocapture nofree readonly, i8* (i8*, i8*)* nocapture nofree readonly, void (i8*)* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_init(%struct.ident_t* nocapture nofree readonly, i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_wait(%struct.ident_t* nocapture nofree readonly, i32, i64* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_post(%struct.ident_t* nocapture nofree readonly, i32, i64* nocapture nofree readonly) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__kmpc_doacross_fini(%struct.ident_t* nocapture nofree readonly, i32) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_alloc(i32, i64, i8*) + +; OPTIMISTIC: ; Function Attrs: nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_free(i32, i8*, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_init_allocator(i32, i8*, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_destroy_allocator(i32, i8*) + +; OPTIMISTIC: ; Function Attrs: inaccessiblememonly nofree nosync nounwind willreturn writeonly +; OPTIMISTIC-NEXT: declare void @__kmpc_push_target_tripcount(i64, i64) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__tgt_target_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__tgt_target_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__tgt_target_teams_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i32 @__tgt_target_teams_nowait_mapper(i64, i8*, i32, i8**, i8**, i64*, i64*, i8**, i32, i32) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_register_requires(i64) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_begin_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_begin_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_end_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_end_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_update_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_target_data_update_nowait_mapper(i64, i32, i8**, i8**, i64*, i64*, i8**) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare i64 @__tgt_mapper_num_components(i8*) + +; OPTIMISTIC: ; Function Attrs: nounwind +; OPTIMISTIC-NEXT: declare void @__tgt_push_mapper_component(i8*, i8*, i8*, i64, i64) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_allow_completion_event(%struct.ident_t* nocapture nofree readonly, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_get_th_data(i32, i8*, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_init(i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare noalias i8* @__kmpc_task_reduction_modifier_init(i8*, i32, i32, i32, i8*) + +; OPTIMISTIC: ; Function Attrs: nofree nosync nounwind willreturn +; OPTIMISTIC-NEXT: declare void @__kmpc_proxy_task_completed_ooo(i8*) diff --git a/llvm/test/Transforms/OpenMP/parallel_deletion.ll b/llvm/test/Transforms/OpenMP/parallel_deletion.ll index 4d2f8e7cbc5e8..07976660546f8 100644 --- a/llvm/test/Transforms/OpenMP/parallel_deletion.ll +++ b/llvm/test/Transforms/OpenMP/parallel_deletion.ll @@ -393,7 +393,7 @@ entry: define internal void @.omp.reduction.reduction_func(i8* %arg, i8* %arg1) { ; CHECK-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func -; CHECK-SAME: (i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #10 +; CHECK-SAME: (i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #{{[0-9]+}} ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP:%.*]] = bitcast i8* [[ARG1]] to i32** ; CHECK-NEXT: [[TMP2:%.*]] = load i32*, i32** [[TMP]], align 8 From 0b2a92224630f6e177d091b8391cfa943764aba5 Mon Sep 17 00:00:00 2001 From: Artem Dergachev Date: Fri, 17 Jul 2020 19:42:20 -0700 Subject: [PATCH 728/771] [analyzer] scan-build: Fix silencing multiple core checkers. It was only silencing one checker because -analyzer-config flags can only carry one value at a time. --- .../null_dereference_and_division_by_zero.c | 8 +++++ .../scan-build/silence-core-checkers.test | 30 +++++++++++++++++++ clang/tools/scan-build/bin/scan-build | 10 ++++--- 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 clang/test/Analysis/scan-build/Inputs/null_dereference_and_division_by_zero.c create mode 100644 clang/test/Analysis/scan-build/silence-core-checkers.test diff --git a/clang/test/Analysis/scan-build/Inputs/null_dereference_and_division_by_zero.c b/clang/test/Analysis/scan-build/Inputs/null_dereference_and_division_by_zero.c new file mode 100644 index 0000000000000..438af79c90bbd --- /dev/null +++ b/clang/test/Analysis/scan-build/Inputs/null_dereference_and_division_by_zero.c @@ -0,0 +1,8 @@ +int test(int x) { + if (x) { + int *p = 0; + return *p; // Null dereference. + } else { + return 1 / x; // Division by zero. + } +} diff --git a/clang/test/Analysis/scan-build/silence-core-checkers.test b/clang/test/Analysis/scan-build/silence-core-checkers.test new file mode 100644 index 0000000000000..6d9a3017fcd61 --- /dev/null +++ b/clang/test/Analysis/scan-build/silence-core-checkers.test @@ -0,0 +1,30 @@ +// FIXME: Actually, "perl". +REQUIRES: shell + +RUN: rm -rf %t.output_dir && mkdir %t.output_dir +RUN: %scan-build -o %t.output_dir \ +RUN: %clang -S %S/Inputs/null_dereference_and_division_by_zero.c \ +RUN: | FileCheck %s -check-prefix CHECK-TWO-BUGS + +RUN: rm -rf %t.output_dir && mkdir %t.output_dir +RUN: %scan-build -o %t.output_dir \ +RUN: -disable-checker core.DivideZero \ +RUN: %clang -S %S/Inputs/null_dereference_and_division_by_zero.c \ +RUN: | FileCheck %s -check-prefix CHECK-ONE-BUG + +RUN: rm -rf %t.output_dir && mkdir %t.output_dir +RUN: %scan-build -o %t.output_dir \ +RUN: -disable-checker core.NullDereference \ +RUN: %clang -S %S/Inputs/null_dereference_and_division_by_zero.c \ +RUN: | FileCheck %s -check-prefix CHECK-ONE-BUG + +RUN: rm -rf %t.output_dir && mkdir %t.output_dir +RUN: %scan-build -o %t.output_dir \ +RUN: -disable-checker core.NullDereference \ +RUN: -disable-checker core.DivideZero \ +RUN: %clang -S %S/Inputs/null_dereference_and_division_by_zero.c \ +RUN: | FileCheck %s -check-prefix CHECK-NO-BUGS + +CHECK-NO-BUGS: scan-build: No bugs found. +CHECK-ONE-BUG: scan-build: 1 bug found. +CHECK-TWO-BUGS: scan-build: 2 bugs found. diff --git a/clang/tools/scan-build/bin/scan-build b/clang/tools/scan-build/bin/scan-build index 11334a0b96269..aed8c417b6ccd 100755 --- a/clang/tools/scan-build/bin/scan-build +++ b/clang/tools/scan-build/bin/scan-build @@ -1973,11 +1973,13 @@ my $CCC_ANALYZER_ANALYSIS = join ' ', @AnalysesToRun; my $CCC_ANALYZER_PLUGINS = join ' ', map { "-load ".$_ } @{$Options{PluginsToLoad}}; my $CCC_ANALYZER_CONFIG = join ' ', map { "-analyzer-config ".$_ } @{$Options{ConfigOptions}}; -foreach (sort { $Options{SilenceCheckers}{$a} <=> $Options{SilenceCheckers}{$b} } - keys %{$Options{SilenceCheckers}}) { - # Add checkers in order they were silenced. +if (%{$Options{SilenceCheckers}}) { $CCC_ANALYZER_CONFIG = - $CCC_ANALYZER_CONFIG." -analyzer-config silence-checkers=".$_; + $CCC_ANALYZER_CONFIG." -analyzer-config silence-checkers=" + .join(';', sort { + $Options{SilenceCheckers}{$a} <=> + $Options{SilenceCheckers}{$b} + } keys %{$Options{SilenceCheckers}}); } my %EnvVars = ( From e79a86e45b21cacc57e0cb8bd40d137d8768fc26 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 17 Jul 2020 11:14:28 -0700 Subject: [PATCH 729/771] [flang] Insert leading blanks in LOGICAL formatted output fields Summary: For Lw output editing, emit (w-1) blanks before the T or the F. Reviewed By: sscalpone, PeteSteinfeld Differential Revision: https://reviews.llvm.org/D84059 --- flang/runtime/edit-output.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flang/runtime/edit-output.cpp b/flang/runtime/edit-output.cpp index 941c5ccf3d593..4680c81129ed2 100644 --- a/flang/runtime/edit-output.cpp +++ b/flang/runtime/edit-output.cpp @@ -424,7 +424,8 @@ bool EditLogicalOutput(IoStatementState &io, const DataEdit &edit, bool truth) { switch (edit.descriptor) { case 'L': case 'G': - return io.Emit(truth ? "T" : "F", 1); + return io.EmitRepeated(' ', std::max(0, edit.width.value_or(1) - 1)) && + io.Emit(truth ? "T" : "F", 1); default: io.GetIoErrorHandler().SignalError(IostatErrorInFormat, "Data edit descriptor '%c' may not be used with a LOGICAL data item", From ca1cc5c4e067d496e92e775bd0ac30c1b775bb62 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 18 Jul 2020 11:10:18 -0700 Subject: [PATCH 730/771] [gcov][test] Call wait() to make gcov-fork.c reliable If the parent exit before the child, the line counts might be 1. next:18'0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26: 1: 21: if (fork() == -1) return 1; // CHECK-NEXT: 1: [[#@LINE]]: next:18'0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27: 1: 22: func2(); // CHECK-NEXT: 2: [[#@LINE]]: next:18'0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28: 1: 23: return 0; // CHECK-NEXT: 2: [[#@LINE]]: next:18'0 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- compiler-rt/test/profile/Posix/gcov-fork.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler-rt/test/profile/Posix/gcov-fork.c b/compiler-rt/test/profile/Posix/gcov-fork.c index 4942d5ac92888..022ce716a8dcb 100644 --- a/compiler-rt/test/profile/Posix/gcov-fork.c +++ b/compiler-rt/test/profile/Posix/gcov-fork.c @@ -1,10 +1,6 @@ /// A basic block with fork/exec* is split. .gcda is flushed immediately before /// fork/exec* so the lines before fork are counted once while succeeding /// lines are counted twice. -// UNSUPPORTED: darwin -/// FIXME: http://lab.llvm.org:8011/builders/clang-ppc64be-linux/builds/50913 -// UNSUPPORTED: host-byteorder-big-endian - // RUN: mkdir -p %t.d && cd %t.d // RUN: %clang --coverage %s -o %t // RUN: test -f gcov-fork.gcno @@ -17,8 +13,12 @@ void func1() {} // CHECK: 1: [[#@LINE]]:void func1() void func2() {} // CHECK-NEXT: 2: [[#@LINE]]: int main(void) { // CHECK-NEXT: 1: [[#@LINE]]: + int status; // CHECK-NEXT: -: [[#@LINE]]: func1(); // CHECK-NEXT: 1: [[#@LINE]]: - if (fork() == -1) return 1; // CHECK-NEXT: 1: [[#@LINE]]: + pid_t pid = fork(); // CHECK-NEXT: 1: [[#@LINE]]: + if (pid == -1) return 1; // CHECK-NEXT: 2: [[#@LINE]]: + if (pid) // CHECK-NEXT: 2: [[#@LINE]]: + wait(&status); // CHECK-NEXT: 1: [[#@LINE]]: func2(); // CHECK-NEXT: 2: [[#@LINE]]: return 0; // CHECK-NEXT: 2: [[#@LINE]]: } From cbff0c75b9ea120bc6ec1ecc2e8d431fd6143236 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 17 Jul 2020 11:17:39 -0700 Subject: [PATCH 731/771] [flang] Improve output from a STOP statement Add a missing newline to IEEE FP flag formatting, and don't neglect to emit STOP when there's no code number. Reviewed By: tskeith Differential Revision: https://reviews.llvm.org/D84060 --- flang/runtime/stop.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp index 49592b75a2ade..3b8c1385293ad 100644 --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -40,6 +40,7 @@ static void DescribeIEEESignaledExceptions() { if (excepts & FE_UNDERFLOW) { std::fputs(" UNDERFLOW", stderr); } + std::fputc('\n', stderr); } } @@ -52,10 +53,11 @@ static void CloseAllExternalUnits(const char *why) { int code, bool isErrorStop, bool quiet) { CloseAllExternalUnits("STOP statement"); if (!quiet) { + std::fprintf(stderr, "Fortran %s", isErrorStop ? "ERROR STOP" : "STOP"); if (code != EXIT_SUCCESS) { - std::fprintf(stderr, "Fortran %s: code %d\n", - isErrorStop ? "ERROR STOP" : "STOP", code); + std::fprintf(stderr, ": code %d\n", code); } + std::fputc('\n', stderr); DescribeIEEESignaledExceptions(); } std::exit(code); From 32db24a7f24236d78beaeb5cfd96b115d67a5c21 Mon Sep 17 00:00:00 2001 From: Bruno Ricci Date: Sat, 18 Jul 2020 20:35:16 +0100 Subject: [PATCH 732/771] [clang] Provide a more specific diagnostic for a misplaced lambda capture-default. Currently a capture-default which is not the first element in the lambda-capture is diagnosed with a generic expected variable name or 'this' in lambda capture list, which is true but not very helpful. If we don't have already parsed a capture-default then a lone "&" or "=" is likely to be a misplaced capture-default, so diagnose it as such. Differential Revision: https://reviews.llvm.org/D83681 Reviewed By: aaron.ballman --- .../clang/Basic/DiagnosticParseKinds.td | 2 + clang/lib/Parse/ParseExprCXX.cpp | 9 +++++ .../lambda-misplaced-capture-default.cpp | 38 +++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 clang/test/Parser/lambda-misplaced-capture-default.cpp diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 1038a4119d4cb..a10191e91be38 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -934,6 +934,8 @@ def err_lambda_capture_misplaced_ellipsis : Error< "the name of the capture">; def err_lambda_capture_multiple_ellipses : Error< "multiple ellipses in pack capture">; +def err_capture_default_first : Error< + "capture default must be first">; // C++17 lambda expressions def err_expected_star_this_capture : Error< "expected 'this' following '*' in lambda capture list">; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index aa35200c33b66..b225bb7c8b36c 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -926,6 +926,15 @@ bool Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, } else if (Tok.is(tok::kw_this)) { Kind = LCK_This; Loc = ConsumeToken(); + } else if (Tok.isOneOf(tok::amp, tok::equal) && + NextToken().isOneOf(tok::comma, tok::r_square) && + Intro.Default == LCD_None) { + // We have a lone "&" or "=" which is either a misplaced capture-default + // or the start of a capture (in the "&" case) with the rest of the + // capture missing. Both are an error but a misplaced capture-default + // is more likely if we don't already have a capture default. + return Invalid( + [&] { Diag(Tok.getLocation(), diag::err_capture_default_first); }); } else { TryConsumeToken(tok::ellipsis, EllipsisLocs[0]); diff --git a/clang/test/Parser/lambda-misplaced-capture-default.cpp b/clang/test/Parser/lambda-misplaced-capture-default.cpp new file mode 100644 index 0000000000000..d65b875102da7 --- /dev/null +++ b/clang/test/Parser/lambda-misplaced-capture-default.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -std=c++20 -Wno-unused-value -fsyntax-only -verify %s + +namespace misplaced_capture_default { +void Test() { + int i = 0; + [&, i, &] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} + [&, i, = ] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} + [=, &i, &] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} + [=, &i, = ] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} + + [i, &] {}; // expected-error {{capture default must be first}} + [i, = ] {}; // expected-error {{capture default must be first}} + [i, = x] {}; // expected-error {{expected variable name or 'this' in lambda capture list}} + [=, &i] {}; // ok + [&, &i] {}; // expected-error {{'&' cannot precede a capture when the capture default is '&'}} + [&x = i] {}; // ok + [=, &x = i] {}; // ok + [x = &i] {}; // ok + [=, &x = &i] {}; // expected-error {{non-const lvalue reference to type 'int *' cannot bind to a temporary of type 'int *'}} + [&, this] {}; // expected-error {{'this' cannot be captured in this context}} + + [i, &, x = 2] {}; // expected-error {{capture default must be first}} + [i, =, x = 2] {}; // expected-error {{capture default must be first}} +} +} // namespace misplaced_capture_default + +namespace misplaced_capture_default_pack { +template void Test(Args... args) { + [&, args...] {}; // ok + [args..., &] {}; // expected-error {{capture default must be first}} + [=, &args...] {}; // ok + [&, ... xs = &args] {}; // ok + [&, ... xs = &] {}; // expected-error {{expected expression}} + [... xs = &] {}; // expected-error {{expected expression}} + [... xs = &args, = ] {}; // expected-error {{capture default must be first}} + [... xs = &args, &] {}; // expected-error {{capture default must be first}} +} +} // namespace misplaced_capture_default_pack From be8e5fee91b44522056f1e780cdc861427f8738f Mon Sep 17 00:00:00 2001 From: Bruno Ricci Date: Sat, 18 Jul 2020 20:39:16 +0100 Subject: [PATCH 733/771] [clang][NFC] Tests showing the problems with some uses of NamedDecl::getDeclName in diagnostics, SemaExpr.cpp part --- .../dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp | 14 +++++++++++++- clang/test/SemaCXX/attr-unused.cpp | 10 ++++++++++ clang/test/SemaCXX/default2.cpp | 6 ++++++ clang/test/SemaCXX/incomplete-call.cpp | 6 ++++-- clang/test/SemaCXX/lambda-expressions.cpp | 11 +++++++++++ 5 files changed, 44 insertions(+), 3 deletions(-) diff --git a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp index af2e7cf09ceb4..52986faa4e859 100644 --- a/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp +++ b/clang/test/CXX/dcl.decl/dcl.meaning/dcl.fct.default/p7.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s void h() { int i1 = 0; @@ -16,4 +16,16 @@ void h() { const int i4 = 0; extern void h4(int x = sizeof(i4)); // ok, not odr-use extern void h5(int x = decltype(i4 + 4)()); // ok, not odr-use + + union { + int i5; + }; + + extern void h6(int = i5); + // expected-error@-1 {{default argument references local variable '' of enclosing function}} + + struct S { int i; }; + auto [x] = S(); + + extern void h7(int = x); // FIXME: reject } diff --git a/clang/test/SemaCXX/attr-unused.cpp b/clang/test/SemaCXX/attr-unused.cpp index b74bc915ce070..e3878152eca97 100644 --- a/clang/test/SemaCXX/attr-unused.cpp +++ b/clang/test/SemaCXX/attr-unused.cpp @@ -3,7 +3,17 @@ namespace ns_unused { typedef int Int_unused __attribute__((unused)); } namespace ns_not_unused { typedef int Int_not_unused; } +template class C; +template <> class __attribute__((unused)) C {}; + void f() { ns_not_unused::Int_not_unused i1; // expected-warning {{unused variable}} ns_unused::Int_unused i0; // expected-warning {{'Int_unused' was marked unused but was used}} + + union __attribute__((unused)) { // expected-warning {{'' was marked unused but was used}} + int i; + }; + (void) i; + + C(); // expected-warning {{'C' was marked unused but was used}} } diff --git a/clang/test/SemaCXX/default2.cpp b/clang/test/SemaCXX/default2.cpp index 4c8e8ce6941a4..7651233f8636f 100644 --- a/clang/test/SemaCXX/default2.cpp +++ b/clang/test/SemaCXX/default2.cpp @@ -117,6 +117,12 @@ class C2 { static int f(int = 10); // expected-note{{default argument declared here}} }; +template class C3; +template <> class C3 { + static void g(int = f()); // expected-error {{use of default argument to function 'f' that is declared later in class 'C3'}} + static int f(int = 10); // expected-note {{default argument declared here}} +}; + // Make sure we actually parse the default argument for an inline definition class XX { void A(int length = -1 ) { } diff --git a/clang/test/SemaCXX/incomplete-call.cpp b/clang/test/SemaCXX/incomplete-call.cpp index 0fb1ef5f07a50..46f470e4a8810 100644 --- a/clang/test/SemaCXX/incomplete-call.cpp +++ b/clang/test/SemaCXX/incomplete-call.cpp @@ -1,7 +1,8 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -struct A; // expected-note 14 {{forward declaration of 'A'}} +struct A; // expected-note 15 {{forward declaration of 'A'}} A f(); // expected-note {{'f' declared here}} +template A ft(T); // expected-note {{'ft' declared here}} struct B { A f(); // expected-note {{'f' declared here}} @@ -38,7 +39,8 @@ void g() { A (B::*mfp)() = 0; (b.*mfp)(); // expected-error {{calling function with incomplete return type 'A'}} - + + ft(42); // expected-error {{calling 'ft' with incomplete return type 'A'}} } diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 3240d5351fc5b..7f7f9c5704872 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -649,3 +649,14 @@ void Run(const int& points) { void operator_parens() { [&](int x){ operator()(); }(0); // expected-error {{undeclared 'operator()'}} } + +namespace captured_name { +void Test() { + union { // expected-note {{'' declared here}} + int i; + }; + [] { return i; }; // expected-error {{variable '' cannot be implicitly captured in a lambda with no capture-default specified}} + // expected-note@-1 {{lambda expression begins here}} + +} +}; From acf3bdc283ecf6e2c3a85a391a24becc4814b8b8 Mon Sep 17 00:00:00 2001 From: Bruno Ricci Date: Sat, 18 Jul 2020 20:44:06 +0100 Subject: [PATCH 734/771] [clang][NFC] Tests showing the problems with some uses of NamedDecl::getDeclName in diagnostics, SemaOverload.cpp+SemaStmt.cpp part --- .../dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp | 6 ++++ clang/test/Sema/return-non-void.c | 5 +++ .../SemaCXX/constant-expression-cxx11.cpp | 5 +++ clang/test/SemaCXX/consteval-return-void.cpp | 10 ++++++ clang/test/SemaCXX/return-void.cpp | 26 +++++++++++++++ clang/test/SemaCXX/return.cpp | 12 ++++++- .../warn-pure-virtual-call-from-ctor-dtor.cpp | 32 +++++++++++++++++++ clang/test/SemaCXX/warn-pure-virtual-kext.cpp | 12 +++++++ clang/test/SemaObjC/method-return-void.m | 9 ++++++ 9 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 clang/test/Sema/return-non-void.c create mode 100644 clang/test/SemaCXX/consteval-return-void.cpp create mode 100644 clang/test/SemaCXX/return-void.cpp create mode 100644 clang/test/SemaObjC/method-return-void.m diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp index 59cac367dbf23..0d4d34ac0e147 100644 --- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.noreturn/p1.cpp @@ -7,6 +7,12 @@ void a2 [[noreturn]] () { return; // expected-warning {{function 'a2' declared 'noreturn' should not return}} } +template void a3 [[noreturn]] () {} +template <> void a3 () { return; } // expected-warning {{function 'a3' declared 'noreturn' should not return}} + +template void a4 [[noreturn]] () { return; } // expected-warning 2{{function 'a4' declared 'noreturn' should not return}} +void a4_test() { a4(); } // expected-note {{in instantiation of function template specialization 'a4' requested here}} + [[noreturn, noreturn]] void b() { throw 0; } // expected-error {{attribute 'noreturn' cannot appear multiple times in an attribute specifier}} [[noreturn]] [[noreturn]] void b2() { throw 0; } // ok diff --git a/clang/test/Sema/return-non-void.c b/clang/test/Sema/return-non-void.c new file mode 100644 index 0000000000000..f1ee3722af489 --- /dev/null +++ b/clang/test/Sema/return-non-void.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -Wreturn-type -std=c99 -fsyntax-only -verify=c99 %s +// RUN: %clang_cc1 -Wreturn-type -std=c90 -fsyntax-only -verify=c90 %s + +int foo(void) { return; } // c99-error {{non-void function 'foo' should return a value}} + // c90-error@-1 {{non-void function 'foo' should return a value}} diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index b69bcb2fef9d0..7ff260c37c698 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2167,6 +2167,11 @@ namespace PR21786 { namespace PR21859 { constexpr int Fun() { return; } // expected-error {{non-void constexpr function 'Fun' should return a value}} constexpr int Var = Fun(); + + template constexpr int FunT1() { return; } // expected-error {{non-void constexpr function 'FunT1' should return a value}} + template constexpr int FunT2() { return 0; } + template <> constexpr int FunT2() { return 0; } + template <> constexpr int FunT2() { return; } // expected-error {{non-void constexpr function 'FunT2' should return a value}} } struct InvalidRedef { diff --git a/clang/test/SemaCXX/consteval-return-void.cpp b/clang/test/SemaCXX/consteval-return-void.cpp new file mode 100644 index 0000000000000..a5207f41bf2c7 --- /dev/null +++ b/clang/test/SemaCXX/consteval-return-void.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +consteval int Fun() { return; } // expected-error {{non-void constexpr function 'Fun' should return a value}} + +// FIXME: The diagnostic is wrong; should be "consteval". + +template consteval int FunT1() { return; } // expected-error {{non-void constexpr function 'FunT1' should return a value}} +template consteval int FunT2() { return 0; } +template <> consteval int FunT2() { return 0; } +template <> consteval int FunT2() { return; } // expected-error {{non-void constexpr function 'FunT2' should return a value}} diff --git a/clang/test/SemaCXX/return-void.cpp b/clang/test/SemaCXX/return-void.cpp new file mode 100644 index 0000000000000..b3aa203133dc3 --- /dev/null +++ b/clang/test/SemaCXX/return-void.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify + +void f1() { return {1,2}; } // expected-error {{void function 'f1' must not return a value}} + +template void f2() { return {1,2}; } // expected-error {{void function 'f2' must not return a value}} + +template <> void f2() { return {1,2}; } // expected-error {{void function 'f2' must not return a value}} + +void test_f2() { + f2(); + f2(); +} + +struct S { + void f3() { return {1,2}; } // expected-error {{void function 'f3' must not return a value}} + S() { return {1,2}; } // expected-error {{constructor 'S' must not return a value}} + ~S() { return {1,2}; } // expected-error {{destructor '~S' must not return a value}} +}; + +template struct ST { + void f4() { return {1,2}; } // expected-error {{void function 'f4' must not return a value}} + ST() { return {1,2}; } // expected-error {{constructor 'ST' must not return a value}} + ~ST() { return {1,2}; } // expected-error {{destructor '~ST' must not return a value}} +}; + +ST st; diff --git a/clang/test/SemaCXX/return.cpp b/clang/test/SemaCXX/return.cpp index db289240d1ce6..1550d009b0617 100644 --- a/clang/test/SemaCXX/return.cpp +++ b/clang/test/SemaCXX/return.cpp @@ -108,9 +108,19 @@ namespace return_has_expr { namespace ctor_returns_void { void f() {} struct S { - S() { return f(); }; // expected-error {{constructor 'S' must not return void expression}} + S() { return f(); } // expected-error {{constructor 'S' must not return void expression}} ~S() { return f(); } // expected-error {{destructor '~S' must not return void expression}} }; + + template struct ST { + ST() { return f(); } // expected-error {{constructor 'ST' must not return void expression}} + // expected-error@-1 {{constructor 'ST' must not return void expression}} + ~ST() { return f(); } // expected-error {{destructor '~ST' must not return void expression}} + // expected-error@-1 {{destructor '~ST' must not return void expression}} + }; + + ST st; // expected-note {{in instantiation of member function 'ctor_returns_void::ST::ST'}} + // expected-note@-1 {{in instantiation of member function 'ctor_returns_void::ST::~ST'}} } void cxx_unresolved_expr() { diff --git a/clang/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp b/clang/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp index 3312b5635f062..789935e3470ac 100644 --- a/clang/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp +++ b/clang/test/SemaCXX/warn-pure-virtual-call-from-ctor-dtor.cpp @@ -20,3 +20,35 @@ struct C { C::f(); } }; + +template struct TA { + TA() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the constructor of 'TA'}} + ~TA() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the destructor of 'TA'}} + + virtual void f() = 0; // expected-note 2{{'f' declared here}} +}; + +template <> struct TA { + TA() { f(); } + ~TA() { f(); } + void f(); +}; + +template <> struct TA { + TA() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the constructor of 'TA'}} + ~TA() { f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the destructor of 'TA'}} + virtual void f() = 0; // expected-note 2{{'f' declared here}} +}; + +struct TB : TA { // expected-note {{in instantiation of member function 'TA::TA' requested here}} + void f() override; // expected-note@-1 {{in instantiation of member function 'TA::~TA' requested here}} +}; +TB tb; + +struct TC : TA {}; // ok +TC tc; // ok + +struct TD : TA { + void f() override; +}; +TD td; diff --git a/clang/test/SemaCXX/warn-pure-virtual-kext.cpp b/clang/test/SemaCXX/warn-pure-virtual-kext.cpp index e681a02cc9166..8431e202ad714 100644 --- a/clang/test/SemaCXX/warn-pure-virtual-kext.cpp +++ b/clang/test/SemaCXX/warn-pure-virtual-kext.cpp @@ -6,3 +6,15 @@ struct A { A::f(); // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the constructor of 'A'}} // expected-note {{qualified call to 'A'::'f' is treated as a virtual call to 'f' due to -fapple-kext}} } }; + +template struct TA { + virtual void f() = 0; // expected-note {{'f' declared here}} + + TA() { TA::f(); } // expected-warning {{call to pure virtual member function 'f' has undefined behavior; overrides of 'f' in subclasses are not available in the constructor of 'TA'}} // expected-note {{qualified call to 'TA'::'f' is treated as a virtual call to 'f' due to -fapple-kext}} +}; + +struct B : TA { // expected-note {{in instantiation of member function 'TA::TA' requested here}} + void f() override; +}; + +B b; diff --git a/clang/test/SemaObjC/method-return-void.m b/clang/test/SemaObjC/method-return-void.m new file mode 100644 index 0000000000000..850c81bad1fca --- /dev/null +++ b/clang/test/SemaObjC/method-return-void.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -Wmethod-signatures -fsyntax-only -verify -Wno-objc-root-class %s + +@interface Test +- (int)foo; +@end + +@implementation Test +- (int)foo { return; } // expected-error {{non-void method 'foo' should return a value}} +@end From 13ae440de4a408cf9d1a448def09769ecbecfdf7 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 18 Jul 2020 23:36:42 +0200 Subject: [PATCH 735/771] [InstCombine] Add test for PR46680 (NFC) --- llvm/test/Transforms/InstCombine/pr46680.ll | 92 +++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/pr46680.ll diff --git a/llvm/test/Transforms/InstCombine/pr46680.ll b/llvm/test/Transforms/InstCombine/pr46680.ll new file mode 100644 index 0000000000000..90ea2e110afe4 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/pr46680.ll @@ -0,0 +1,92 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instcombine -instcombine-infinite-loop-threshold=3 < %s | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +@a = dso_local local_unnamed_addr global i64 0, align 8 +@d = dso_local local_unnamed_addr global i64 0, align 8 +@c = external dso_local local_unnamed_addr global i8, align 1 + +define void @test(i16* nocapture readonly %arg) local_unnamed_addr { +; CHECK-LABEL: @test( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[I:%.*]] = load i64, i64* @d, align 8 +; CHECK-NEXT: [[I1:%.*]] = icmp eq i64 [[I]], 0 +; CHECK-NEXT: [[I2:%.*]] = load i64, i64* @a, align 8 +; CHECK-NEXT: [[I3:%.*]] = icmp ne i64 [[I2]], 0 +; CHECK-NEXT: br i1 [[I1]], label [[BB13:%.*]], label [[BB4:%.*]] +; CHECK: bb4: +; CHECK-NEXT: [[I5:%.*]] = load i16, i16* [[ARG:%.*]], align 2 +; CHECK-NEXT: [[I6:%.*]] = trunc i16 [[I5]] to i8 +; CHECK-NEXT: store i8 [[I6]], i8* @c, align 1 +; CHECK-NEXT: tail call void @llvm.assume(i1 [[I3]]) +; CHECK-NEXT: br label [[BB22:%.*]] +; CHECK: bb13: +; CHECK-NEXT: [[I14:%.*]] = load i16, i16* [[ARG]], align 2 +; CHECK-NEXT: [[I15:%.*]] = trunc i16 [[I14]] to i8 +; CHECK-NEXT: store i8 [[I15]], i8* @c, align 1 +; CHECK-NEXT: br label [[BB22]] +; CHECK: bb22: +; CHECK-NEXT: [[STOREMERGE2_IN:%.*]] = load i16, i16* [[ARG]], align 2 +; CHECK-NEXT: [[STOREMERGE2:%.*]] = trunc i16 [[STOREMERGE2_IN]] to i8 +; CHECK-NEXT: store i8 [[STOREMERGE2]], i8* @c, align 1 +; CHECK-NEXT: [[STOREMERGE1_IN:%.*]] = load i16, i16* [[ARG]], align 2 +; CHECK-NEXT: [[STOREMERGE1:%.*]] = trunc i16 [[STOREMERGE1_IN]] to i8 +; CHECK-NEXT: store i8 [[STOREMERGE1]], i8* @c, align 1 +; CHECK-NEXT: [[STOREMERGE_IN:%.*]] = load i16, i16* [[ARG]], align 2 +; CHECK-NEXT: [[STOREMERGE:%.*]] = trunc i16 [[STOREMERGE_IN]] to i8 +; CHECK-NEXT: store i8 [[STOREMERGE]], i8* @c, align 1 +; CHECK-NEXT: br label [[BB23:%.*]] +; CHECK: bb23: +; CHECK-NEXT: br label [[BB23]] +; +bb: + %i = load i64, i64* @d, align 8 + %i1 = icmp eq i64 %i, 0 + %i2 = load i64, i64* @a, align 8 + %i3 = icmp ne i64 %i2, 0 + br i1 %i1, label %bb13, label %bb4 + +bb4: ; preds = %bb + %i5 = load i16, i16* %arg, align 2 + %i6 = trunc i16 %i5 to i8 + store i8 %i6, i8* @c, align 1 + tail call void @llvm.assume(i1 %i3) + %i7 = load i16, i16* %arg, align 2 + %i8 = trunc i16 %i7 to i8 + store i8 %i8, i8* @c, align 1 + %i9 = load i16, i16* %arg, align 2 + %i10 = trunc i16 %i9 to i8 + store i8 %i10, i8* @c, align 1 + %i11 = load i16, i16* %arg, align 2 + %i12 = trunc i16 %i11 to i8 + store i8 %i12, i8* @c, align 1 + br label %bb22 + +bb13: ; preds = %bb + %i14 = load i16, i16* %arg, align 2 + %i15 = trunc i16 %i14 to i8 + store i8 %i15, i8* @c, align 1 + %i16 = load i16, i16* %arg, align 2 + %i17 = trunc i16 %i16 to i8 + store i8 %i17, i8* @c, align 1 + %i18 = load i16, i16* %arg, align 2 + %i19 = trunc i16 %i18 to i8 + store i8 %i19, i8* @c, align 1 + %i20 = load i16, i16* %arg, align 2 + %i21 = trunc i16 %i20 to i8 + store i8 %i21, i8* @c, align 1 + br label %bb22 + +bb22: ; preds = %bb13, %bb4 + br label %bb23 + +bb23: ; preds = %bb23, %bb22 + br label %bb23 +} + +; Function Attrs: nounwind willreturn +declare void @llvm.assume(i1) #0 + +attributes #0 = { nounwind willreturn } From 6a25838be6a0b242443320559cf1f97f466c59cc Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 11 Jul 2020 17:17:21 -0700 Subject: [PATCH 736/771] [gcov][test] Simplify instrprof-dlopen-dlclose-gcov.test --- .../instrprof-dlopen-dlclose-main.c.gcov | 91 ------------------- ...prof-dlopen-dlclose-main_three-libs.c.gcov | 91 ------------------- .../Inputs/instrprof-dlopen-func.c.gcov | 6 -- .../Inputs/instrprof-dlopen-func2.c.gcov | 6 -- .../Inputs/instrprof-dlopen-func3.c.gcov | 6 -- compiler-rt/test/profile/Posix/gcov-dlopen.c | 82 +++++++++++++++++ .../Posix/instrprof-dlopen-dlclose-gcov.test | 33 ------- 7 files changed, 82 insertions(+), 233 deletions(-) delete mode 100644 compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c.gcov delete mode 100644 compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov delete mode 100644 compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c.gcov delete mode 100644 compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c.gcov delete mode 100644 compiler-rt/test/profile/Inputs/instrprof-dlopen-func3.c.gcov create mode 100644 compiler-rt/test/profile/Posix/gcov-dlopen.c delete mode 100644 compiler-rt/test/profile/Posix/instrprof-dlopen-dlclose-gcov.test diff --git a/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c.gcov deleted file mode 100644 index 2d538f63eb46b..0000000000000 --- a/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c.gcov +++ /dev/null @@ -1,91 +0,0 @@ -// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-dlclose-main.c -// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-dlclose-main.gcno -// CHECK-NEXT: -: 0:Data:instrprof-dlopen-dlclose-main.gcda -// CHECK-NEXT: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 -// CHECK-NEXT: -: 1:#include -// CHECK-NEXT: -: 2:#include -// CHECK-NEXT: -: 3:#include -// CHECK-NEXT: -: 4: -// CHECK-NEXT: 1: 5:int main(int argc, char *argv[]) { -// CHECK-NEXT: 1: 6: dlerror(); -// CHECK-NEXT: 1: 7: void *f1_handle = dlopen("func.shared", RTLD_LAZY | RTLD_GLOBAL); -// CHECK-NEXT: 1: 8: if (f1_handle == NULL) { -// CHECK-NEXT: #####: 9: fprintf(stderr, "unable to open 'func.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 10: return EXIT_FAILURE; -// CHECK-NEXT: -: 11: } -// CHECK-NEXT: -: 12: -// CHECK-NEXT: 1: 13: void (*func)(void) = (void (*)(void))dlsym(f1_handle, "func"); -// CHECK-NEXT: 1: 14: if (func == NULL) { -// CHECK-NEXT: #####: 15: fprintf(stderr, "unable to lookup symbol 'func': %s\n", dlerror()); -// CHECK-NEXT: #####: 16: return EXIT_FAILURE; -// CHECK-NEXT: -: 17: } -// CHECK-NEXT: -: 18: -// CHECK-NEXT: 1: 19: dlerror(); -// CHECK-NEXT: 1: 20: void *f2_handle = dlopen("func2.shared", RTLD_LAZY | RTLD_GLOBAL); -// CHECK-NEXT: 1: 21: if (f2_handle == NULL) { -// CHECK-NEXT: #####: 22: fprintf(stderr, "unable to open 'func2.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 23: return EXIT_FAILURE; -// CHECK-NEXT: -: 24: } -// CHECK-NEXT: -: 25: -// CHECK-NEXT: 1: 26: void (*func2)(void) = (void (*)(void))dlsym(f2_handle, "func2"); -// CHECK-NEXT: 1: 27: if (func2 == NULL) { -// CHECK-NEXT: #####: 28: fprintf(stderr, "unable to lookup symbol 'func2': %s\n", dlerror()); -// CHECK-NEXT: #####: 29: return EXIT_FAILURE; -// CHECK-NEXT: -: 30: } -// CHECK-NEXT: 1: 31: func2(); -// CHECK-NEXT: -: 32: -// CHECK-NEXT: -: 33:#ifdef USE_LIB3 -// CHECK-NEXT: -: 34: void *f3_handle = dlopen("func3.shared", RTLD_LAZY | RTLD_GLOBAL); -// CHECK-NEXT: -: 35: if (f3_handle == NULL) { -// CHECK-NEXT: -: 36: fprintf(stderr, "unable to open 'func3.shared': %s\n", dlerror()); -// CHECK-NEXT: -: 37: return EXIT_FAILURE; -// CHECK-NEXT: -: 38: } -// CHECK-NEXT: -: 39: -// CHECK-NEXT: -: 40: void (*func3)(void) = (void (*)(void))dlsym(f3_handle, "func3"); -// CHECK-NEXT: -: 41: if (func3 == NULL) { -// CHECK-NEXT: -: 42: fprintf(stderr, "unable to lookup symbol 'func3': %s\n", dlerror()); -// CHECK-NEXT: -: 43: return EXIT_FAILURE; -// CHECK-NEXT: -: 44: } -// CHECK-NEXT: -: 45: func3(); -// CHECK-NEXT: -: 46:#endif -// CHECK-NEXT: -: 47: -// CHECK-NEXT: 1: 48: dlerror(); -// CHECK-NEXT: 1: 49: void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); -// CHECK-NEXT: 1: 50: if (gcov_flush1 == NULL) { -// CHECK-NEXT: #####: 51: fprintf(stderr, "unable to find __gcov_flush in func.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 52: return EXIT_FAILURE; -// CHECK-NEXT: -: 53: } -// CHECK-NEXT: -: 54: -// CHECK-NEXT: 1: 55: dlerror(); -// CHECK-NEXT: 1: 56: void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); -// CHECK-NEXT: 1: 57: if (gcov_flush2 == NULL) { -// CHECK-NEXT: #####: 58: fprintf(stderr, "unable to find __gcov_flush in func2.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 59: return EXIT_FAILURE; -// CHECK-NEXT: -: 60: } -// CHECK-NEXT: -: 61: -// CHECK-NEXT: 1: 62: if (gcov_flush1 == gcov_flush2) { -// CHECK-NEXT: #####: 63: fprintf(stderr, "Same __gcov_flush found in func.shared and func2.shared\n"); -// CHECK-NEXT: #####: 64: return EXIT_FAILURE; -// CHECK-NEXT: -: 65: } -// CHECK-NEXT: -: 66: -// CHECK-NEXT: 1: 67: dlerror(); -// CHECK-NEXT: 1: 68: if (dlclose(f2_handle) != 0) { -// CHECK-NEXT: #####: 69: fprintf(stderr, "unable to close 'func2.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 70: return EXIT_FAILURE; -// CHECK-NEXT: -: 71: } -// CHECK-NEXT: -: 72: -// CHECK-NEXT: 1: 73: func(); -// CHECK-NEXT: -: 74: -// CHECK-NEXT: 1: 75: int g1 = 0; -// CHECK-NEXT: 1: 76: int g2 = 0; -// CHECK-NEXT: 1: 77: int n = 10; -// CHECK-NEXT: -: 78: -// CHECK-NEXT: 1: 79: if (n % 5 == 0) -// CHECK-NEXT: 1: 80: g1++; -// CHECK-NEXT: -: 81: else -// CHECK-NEXT: #####: 82: g2++; -// CHECK-NEXT: -: 83: -// CHECK-NEXT: 1: 84: return EXIT_SUCCESS; -// CHECK-NEXT: 1: 85:} -// CHECK-NEXT: -: 86: diff --git a/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov deleted file mode 100644 index f1dd1757144f4..0000000000000 --- a/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov +++ /dev/null @@ -1,91 +0,0 @@ -// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-dlclose-main.c -// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-dlclose-main.gcno -// CHECK-NEXT: -: 0:Data:instrprof-dlopen-dlclose-main.gcda -// CHECK-NEXT: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 -// CHECK-NEXT: -: 1:#include -// CHECK-NEXT: -: 2:#include -// CHECK-NEXT: -: 3:#include -// CHECK-NEXT: -: 4: -// CHECK-NEXT: 1: 5:int main(int argc, char *argv[]) { -// CHECK-NEXT: 1: 6: dlerror(); -// CHECK-NEXT: 1: 7: void *f1_handle = dlopen("func.shared", RTLD_LAZY | RTLD_GLOBAL); -// CHECK-NEXT: 1: 8: if (f1_handle == NULL) { -// CHECK-NEXT: #####: 9: fprintf(stderr, "unable to open 'func.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 10: return EXIT_FAILURE; -// CHECK-NEXT: -: 11: } -// CHECK-NEXT: -: 12: -// CHECK-NEXT: 1: 13: void (*func)(void) = (void (*)(void))dlsym(f1_handle, "func"); -// CHECK-NEXT: 1: 14: if (func == NULL) { -// CHECK-NEXT: #####: 15: fprintf(stderr, "unable to lookup symbol 'func': %s\n", dlerror()); -// CHECK-NEXT: #####: 16: return EXIT_FAILURE; -// CHECK-NEXT: -: 17: } -// CHECK-NEXT: -: 18: -// CHECK-NEXT: 1: 19: dlerror(); -// CHECK-NEXT: 1: 20: void *f2_handle = dlopen("func2.shared", RTLD_LAZY | RTLD_GLOBAL); -// CHECK-NEXT: 1: 21: if (f2_handle == NULL) { -// CHECK-NEXT: #####: 22: fprintf(stderr, "unable to open 'func2.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 23: return EXIT_FAILURE; -// CHECK-NEXT: -: 24: } -// CHECK-NEXT: -: 25: -// CHECK-NEXT: 1: 26: void (*func2)(void) = (void (*)(void))dlsym(f2_handle, "func2"); -// CHECK-NEXT: 1: 27: if (func2 == NULL) { -// CHECK-NEXT: #####: 28: fprintf(stderr, "unable to lookup symbol 'func2': %s\n", dlerror()); -// CHECK-NEXT: #####: 29: return EXIT_FAILURE; -// CHECK-NEXT: -: 30: } -// CHECK-NEXT: 1: 31: func2(); -// CHECK-NEXT: -: 32: -// CHECK-NEXT: -: 33:#ifdef USE_LIB3 -// CHECK-NEXT: 1: 34: void *f3_handle = dlopen("func3.shared", RTLD_LAZY | RTLD_GLOBAL); -// CHECK-NEXT: 1: 35: if (f3_handle == NULL) { -// CHECK-NEXT: #####: 36: fprintf(stderr, "unable to open 'func3.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 37: return EXIT_FAILURE; -// CHECK-NEXT: -: 38: } -// CHECK-NEXT: -: 39: -// CHECK-NEXT: 1: 40: void (*func3)(void) = (void (*)(void))dlsym(f3_handle, "func3"); -// CHECK-NEXT: 1: 41: if (func3 == NULL) { -// CHECK-NEXT: #####: 42: fprintf(stderr, "unable to lookup symbol 'func3': %s\n", dlerror()); -// CHECK-NEXT: #####: 43: return EXIT_FAILURE; -// CHECK-NEXT: -: 44: } -// CHECK-NEXT: 1: 45: func3(); -// CHECK-NEXT: -: 46:#endif -// CHECK-NEXT: -: 47: -// CHECK-NEXT: 1: 48: dlerror(); -// CHECK-NEXT: 1: 49: void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); -// CHECK-NEXT: 1: 50: if (gcov_flush1 == NULL) { -// CHECK-NEXT: #####: 51: fprintf(stderr, "unable to find __gcov_flush in func.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 52: return EXIT_FAILURE; -// CHECK-NEXT: -: 53: } -// CHECK-NEXT: -: 54: -// CHECK-NEXT: 1: 55: dlerror(); -// CHECK-NEXT: 1: 56: void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); -// CHECK-NEXT: 1: 57: if (gcov_flush2 == NULL) { -// CHECK-NEXT: #####: 58: fprintf(stderr, "unable to find __gcov_flush in func2.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 59: return EXIT_FAILURE; -// CHECK-NEXT: -: 60: } -// CHECK-NEXT: -: 61: -// CHECK-NEXT: 1: 62: if (gcov_flush1 == gcov_flush2) { -// CHECK-NEXT: #####: 63: fprintf(stderr, "Same __gcov_flush found in func.shared and func2.shared\n"); -// CHECK-NEXT: #####: 64: return EXIT_FAILURE; -// CHECK-NEXT: -: 65: } -// CHECK-NEXT: -: 66: -// CHECK-NEXT: 1: 67: dlerror(); -// CHECK-NEXT: 1: 68: if (dlclose(f2_handle) != 0) { -// CHECK-NEXT: #####: 69: fprintf(stderr, "unable to close 'func2.shared': %s\n", dlerror()); -// CHECK-NEXT: #####: 70: return EXIT_FAILURE; -// CHECK-NEXT: -: 71: } -// CHECK-NEXT: -: 72: -// CHECK-NEXT: 1: 73: func(); -// CHECK-NEXT: -: 74: -// CHECK-NEXT: 1: 75: int g1 = 0; -// CHECK-NEXT: 1: 76: int g2 = 0; -// CHECK-NEXT: 1: 77: int n = 10; -// CHECK-NEXT: -: 78: -// CHECK-NEXT: 1: 79: if (n % 5 == 0) -// CHECK-NEXT: 1: 80: g1++; -// CHECK-NEXT: -: 81: else -// CHECK-NEXT: #####: 82: g2++; -// CHECK-NEXT: -: 83: -// CHECK-NEXT: 1: 84: return EXIT_SUCCESS; -// CHECK-NEXT: 1: 85:} -// CHECK-NEXT: -: 86: diff --git a/compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c.gcov deleted file mode 100644 index 3af4ec94a1b01..0000000000000 --- a/compiler-rt/test/profile/Inputs/instrprof-dlopen-func.c.gcov +++ /dev/null @@ -1,6 +0,0 @@ -// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-func.c -// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-func.gcno -// CHECK-NEXT: -: 0:Data:instrprof-dlopen-func.gcda -// CHECK-NEXT: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 -// CHECK-NEXT: 1: 1:void func(int K) {} diff --git a/compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c.gcov deleted file mode 100644 index 7101f74b938d6..0000000000000 --- a/compiler-rt/test/profile/Inputs/instrprof-dlopen-func2.c.gcov +++ /dev/null @@ -1,6 +0,0 @@ -// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-func2.c -// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-func2.gcno -// CHECK-NEXT: -: 0:Data:instrprof-dlopen-func2.gcda -// CHECK-NEXT: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 -// CHECK-NEXT: 1: 1:void func2(int K) {} diff --git a/compiler-rt/test/profile/Inputs/instrprof-dlopen-func3.c.gcov b/compiler-rt/test/profile/Inputs/instrprof-dlopen-func3.c.gcov deleted file mode 100644 index 7101f74b938d6..0000000000000 --- a/compiler-rt/test/profile/Inputs/instrprof-dlopen-func3.c.gcov +++ /dev/null @@ -1,6 +0,0 @@ -// CHECK: -: 0:Source:{{.*}}Inputs/instrprof-dlopen-func2.c -// CHECK-NEXT: -: 0:Graph:instrprof-dlopen-func2.gcno -// CHECK-NEXT: -: 0:Data:instrprof-dlopen-func2.gcda -// CHECK-NEXT: -: 0:Runs:1 -// CHECK-NEXT: -: 0:Programs:1 -// CHECK-NEXT: 1: 1:void func2(int K) {} diff --git a/compiler-rt/test/profile/Posix/gcov-dlopen.c b/compiler-rt/test/profile/Posix/gcov-dlopen.c new file mode 100644 index 0000000000000..f09129d3b7c46 --- /dev/null +++ b/compiler-rt/test/profile/Posix/gcov-dlopen.c @@ -0,0 +1,82 @@ +/// atexit(3) not supported in dlopen(3)ed+dlclose(3)d DSO +// XFAIL: netbsd + +// RUN: mkdir -p %t.d && cd %t.d + +// RUN: echo 'void func1(int k) {}' > func1.c +// RUN: echo 'void func2(int k) {}' > func2.c +// RUN: echo 'void func3(int k) {}' > func3.c +// RUN: %clang --coverage -fPIC -shared func1.c -o func1.so +// RUN: %clang --coverage -fPIC -shared func2.c -o func2.so +// RUN: %clang --coverage -fPIC -shared func3.c -o func3.so +// RUN: %clang --coverage -fPIC -rpath %t.d %s -o %t + +/// Test with two dlopened libraries. +// RUN: rm -f gcov-dlopen.gcda func1.gcda func2.gcda +// RUN: %run %t +// RUN: llvm-cov gcov -t gcov-dlopen.gcda | FileCheck %s +// RUN: llvm-cov gcov -t func1.gcda | FileCheck %s --check-prefix=FUNC1 +// RUN: llvm-cov gcov -t func2.gcda | FileCheck %s --check-prefix=FUNC2 + +// FUNC1: 1: 1:void func1(int k) {} +// FUNC2: 1: 1:void func2(int k) {} + +/// Test with three dlopened libraries. +// RUN: %clang -DUSE_LIB3 --coverage -fPIC -rpath %t.d %s -o %t +// RUN: rm -f gcov-dlopen.gcda func1.gcda func2.gcda func3.gcda +// RUN: %run %t +// RUN: llvm-cov gcov -t gcov-dlopen.gcda | FileCheck %s --check-prefix=LIB3 +// RUN: llvm-cov gcov -t func1.gcda | FileCheck %s --check-prefix=FUNC1 +// RUN: llvm-cov gcov -t func2.gcda | FileCheck %s --check-prefix=FUNC2 +// RUN: llvm-cov gcov -t func3.gcda | FileCheck %s --check-prefix=FUNC3 + +// FUNC3: 1: 1:void func3(int k) {} + +#include +#include +#include + +int main(int argc, char *argv[]) { + void *f1_handle = dlopen("func1.so", RTLD_LAZY | RTLD_GLOBAL); + if (f1_handle == NULL) + return fprintf(stderr, "unable to open 'func1.so': %s\n", dlerror()); + void (*func1)(void) = (void (*)(void))dlsym(f1_handle, "func1"); + if (func1 == NULL) + return fprintf(stderr, "unable to lookup symbol 'func1': %s\n", dlerror()); + + void *f2_handle = dlopen("func2.so", RTLD_LAZY | RTLD_GLOBAL); + if (f2_handle == NULL) + return fprintf(stderr, "unable to open 'func2.so': %s\n", dlerror()); + void (*func2)(void) = (void (*)(void))dlsym(f2_handle, "func2"); + if (func2 == NULL) + return fprintf(stderr, "unable to lookup symbol 'func2': %s\n", dlerror()); + func2(); + +#ifdef USE_LIB3 +// CHECK: -: [[#@LINE+2]]: void *f3_handle +// LIB3: 1: [[#@LINE+1]]: void *f3_handle + void *f3_handle = dlopen("func3.so", RTLD_LAZY | RTLD_GLOBAL); + if (f3_handle == NULL) + return fprintf(stderr, "unable to open 'func3.so': %s\n", dlerror()); + void (*func3)(void) = (void (*)(void))dlsym(f3_handle, "func3"); + if (func3 == NULL) + return fprintf(stderr, "unable to lookup symbol 'func3': %s\n", dlerror()); + func3(); +#endif + + void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); + if (gcov_flush1 == NULL) + return fprintf(stderr, "unable to find __gcov_flush in func1.so': %s\n", dlerror()); + void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); + if (gcov_flush2 == NULL) + return fprintf(stderr, "unable to find __gcov_flush in func2.so': %s\n", dlerror()); + if (gcov_flush1 == gcov_flush2) + return fprintf(stderr, "same __gcov_flush found in func1.so and func2.so\n"); + + if (dlclose(f2_handle) != 0) + return fprintf(stderr, "unable to close 'func2.so': %s\n", dlerror()); + + func1(); + + return 0; +} diff --git a/compiler-rt/test/profile/Posix/instrprof-dlopen-dlclose-gcov.test b/compiler-rt/test/profile/Posix/instrprof-dlopen-dlclose-gcov.test deleted file mode 100644 index b845303a8afdc..0000000000000 --- a/compiler-rt/test/profile/Posix/instrprof-dlopen-dlclose-gcov.test +++ /dev/null @@ -1,33 +0,0 @@ -# atexit(3) not supported in dlopen(3)ed+dlclose(3)d DSO -XFAIL: netbsd - -RUN: mkdir -p %t.d -RUN: cd %t.d - -RUN: %clang --coverage -o func.shared -fPIC -shared %S/../Inputs/instrprof-dlopen-func.c -RUN: %clang --coverage -o func2.shared -fPIC -shared %S/../Inputs/instrprof-dlopen-func2.c -RUN: %clang --coverage -o func3.shared -fPIC -shared %S/../Inputs/instrprof-dlopen-func3.c -RUN: %clang --coverage -o %t -fPIC -rpath %t.d %S/../Inputs/instrprof-dlopen-dlclose-main.c - -# Test with two dlopened libraries. -RUN: rm -f instrprof-dlopen-dlclose-main.gcda instrprof-dlopen-func.gcda instrprof-dlopen-func2.gcda -RUN: %run %t -RUN: llvm-cov gcov instrprof-dlopen-dlclose-main.gcda -RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-dlclose-main.c.gcov %S/../Inputs/instrprof-dlopen-dlclose-main.c.gcov -RUN: llvm-cov gcov instrprof-dlopen-func.gcda -RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func.c.gcov %S/../Inputs/instrprof-dlopen-func.c.gcov -RUN: llvm-cov gcov instrprof-dlopen-func2.gcda -RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func2.c.gcov %S/../Inputs/instrprof-dlopen-func2.c.gcov - -# Test with three dlopened libraries. -RUN: %clang -DUSE_LIB3 --coverage -o %t -fPIC -rpath %t.d %S/../Inputs/instrprof-dlopen-dlclose-main.c -RUN: rm -f instrprof-dlopen-dlclose-main.gcda instrprof-dlopen-func.gcda instrprof-dlopen-func2.gcda instrprof-dlopen-func3.gcda -RUN: %run %t -RUN: llvm-cov gcov instrprof-dlopen-dlclose-main.gcda -RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-dlclose-main.c.gcov %S/../Inputs/instrprof-dlopen-dlclose-main_three-libs.c.gcov -RUN: llvm-cov gcov instrprof-dlopen-func.gcda -RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func.c.gcov %S/../Inputs/instrprof-dlopen-func.c.gcov -RUN: llvm-cov gcov instrprof-dlopen-func2.gcda -RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func2.c.gcov %S/../Inputs/instrprof-dlopen-func2.c.gcov -RUN: llvm-cov gcov instrprof-dlopen-func3.gcda -RUN: FileCheck --match-full-lines --strict-whitespace --input-file instrprof-dlopen-func2.c.gcov %S/../Inputs/instrprof-dlopen-func3.c.gcov From 5809a32e7c2d79a9a463eb9c15cde994b42e3002 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 18 Jul 2020 15:07:46 -0700 Subject: [PATCH 737/771] [gcov] Add __gcov_dump/__gcov_reset and delete __gcov_flush GCC r187297 (2012-05) introduced `__gcov_dump` and `__gcov_reset`. `__gcov_flush = __gcov_dump + __gcov_reset` The resolution to https://gcc.gnu.org/PR93623 ("No need to dump gcdas when forking" target GCC 11.0) removed the unuseful and undocumented __gcov_flush. Close PR38064. Reviewed By: calixte, serge-sans-paille Differential Revision: https://reviews.llvm.org/D83149 --- clang/lib/Driver/ToolChains/Darwin.cpp | 3 +- clang/test/CodeGen/code-coverage.c | 1 - clang/test/Driver/darwin-ld.c | 3 +- compiler-rt/lib/profile/GCDAProfiling.c | 35 +++++----------- .../Inputs/instrprof-dlopen-dlclose-main.c | 16 +++---- compiler-rt/test/profile/Posix/gcov-dlopen.c | 21 ++++++---- .../test/profile/Posix/gcov-shared-flush.c | 23 ++++++---- .../profile/gcov-__gcov_flush-terminate.c | 6 ++- .../test/profile/gcov-dump-and-remove.c | 13 +++--- .../Instrumentation/GCOVProfiling.cpp | 42 ++----------------- 10 files changed, 65 insertions(+), 98 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 7b879f8cb6521..f910c88fa9674 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -1196,7 +1196,8 @@ void Darwin::addProfileRTLibs(const ArgList &Args, // runtime's functionality. if (hasExportSymbolDirective(Args)) { if (ForGCOV) { - addExportedSymbol(CmdArgs, "___gcov_flush"); + addExportedSymbol(CmdArgs, "___gcov_dump"); + addExportedSymbol(CmdArgs, "___gcov_reset"); addExportedSymbol(CmdArgs, "_flush_fn_list"); addExportedSymbol(CmdArgs, "_writeout_fn_list"); addExportedSymbol(CmdArgs, "_reset_fn_list"); diff --git a/clang/test/CodeGen/code-coverage.c b/clang/test/CodeGen/code-coverage.c index 34ba3554f5b54..5a663135e2f03 100644 --- a/clang/test/CodeGen/code-coverage.c +++ b/clang/test/CodeGen/code-coverage.c @@ -51,7 +51,6 @@ int test2(int b) { // Check that the noredzone flag is set on the generated functions. // CHECK: void @__llvm_gcov_writeout() unnamed_addr [[NRZ:#[0-9]+]] -// CHECK: void @__llvm_gcov_flush() unnamed_addr [[NRZ]] // CHECK: void @__llvm_gcov_init() unnamed_addr [[NRZ]] // CHECK: attributes [[NRZ]] = { {{.*}}noredzone{{.*}} } diff --git a/clang/test/Driver/darwin-ld.c b/clang/test/Driver/darwin-ld.c index 3fc0556a2bde9..ea71142e88c19 100644 --- a/clang/test/Driver/darwin-ld.c +++ b/clang/test/Driver/darwin-ld.c @@ -351,7 +351,8 @@ // RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log // RUN: %clang -target x86_64-apple-darwin12 -fprofile-arcs -Xlinker -exported_symbols_list -Xlinker /dev/null -### %t.o 2> %t.log // RUN: FileCheck -check-prefix=GCOV_EXPORT %s < %t.log -// GCOV_EXPORT: "-exported_symbol" "___gcov_flush" +// GCOV_EXPORT: "-exported_symbol" "___gcov_dump" +// GCOV_EXPORT: "-exported_symbol" "___gcov_reset" // // Check that we can pass the outliner down to the linker. // RUN: env IPHONEOS_DEPLOYMENT_TARGET=7.0 \ diff --git a/compiler-rt/lib/profile/GCDAProfiling.c b/compiler-rt/lib/profile/GCDAProfiling.c index 57d8dec423cc0..fa4b951383324 100644 --- a/compiler-rt/lib/profile/GCDAProfiling.c +++ b/compiler-rt/lib/profile/GCDAProfiling.c @@ -639,25 +639,6 @@ static void llvm_writeout_and_clear(void) { fn_list_remove(&writeout_fn_list); } -COMPILER_RT_VISIBILITY -void llvm_register_flush_function(fn_ptr fn) { - fn_list_insert(&flush_fn_list, fn); -} - -void __gcov_flush() { - struct fn_node* curr = flush_fn_list.head; - - while (curr) { - curr->fn(); - curr = curr->next; - } -} - -COMPILER_RT_VISIBILITY -void llvm_delete_flush_function_list(void) { - fn_list_remove(&flush_fn_list); -} - COMPILER_RT_VISIBILITY void llvm_register_reset_function(fn_ptr fn) { fn_list_insert(&reset_fn_list, fn); @@ -698,15 +679,12 @@ pid_t __gcov_fork() { #endif COMPILER_RT_VISIBILITY -void llvm_gcov_init(fn_ptr wfn, fn_ptr ffn, fn_ptr rfn) { +void llvm_gcov_init(fn_ptr wfn, fn_ptr rfn) { static int atexit_ran = 0; if (wfn) llvm_register_writeout_function(wfn); - if (ffn) - llvm_register_flush_function(ffn); - if (rfn) llvm_register_reset_function(rfn); @@ -715,11 +693,20 @@ void llvm_gcov_init(fn_ptr wfn, fn_ptr ffn, fn_ptr rfn) { /* Make sure we write out the data and delete the data structures. */ atexit(llvm_delete_reset_function_list); - atexit(llvm_delete_flush_function_list); #ifdef _WIN32 atexit(llvm_writeout_and_clear); #endif } } +void __gcov_dump(void) { + for (struct fn_node *f = writeout_fn_list.head; f; f = f->next) + f->fn(); +} + +void __gcov_reset(void) { + for (struct fn_node *f = reset_fn_list.head; f; f = f->next) + f->fn(); +} + #endif diff --git a/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c b/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c index 3f4a4f6cc6a63..416b90384c7d2 100644 --- a/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c +++ b/compiler-rt/test/profile/Inputs/instrprof-dlopen-dlclose-main.c @@ -46,21 +46,21 @@ int main(int argc, char *argv[]) { #endif dlerror(); - void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); - if (gcov_flush1 == NULL) { - fprintf(stderr, "unable to find __gcov_flush in func.shared': %s\n", dlerror()); + void (*gcov_reset1)() = (void (*)())dlsym(f1_handle, "__gcov_reset"); + if (gcov_reset1 == NULL) { + fprintf(stderr, "unable to find __gcov_reset in func.shared': %s\n", dlerror()); return EXIT_FAILURE; } dlerror(); - void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); - if (gcov_flush2 == NULL) { - fprintf(stderr, "unable to find __gcov_flush in func2.shared': %s\n", dlerror()); + void (*gcov_reset2)() = (void (*)())dlsym(f2_handle, "__gcov_reset"); + if (gcov_reset2 == NULL) { + fprintf(stderr, "unable to find __gcov_reset in func2.shared': %s\n", dlerror()); return EXIT_FAILURE; } - if (gcov_flush1 == gcov_flush2) { - fprintf(stderr, "Same __gcov_flush found in func.shared and func2.shared\n"); + if (gcov_reset1 == gcov_reset2) { + fprintf(stderr, "Same __gcov_reset found in func.shared and func2.shared\n"); return EXIT_FAILURE; } diff --git a/compiler-rt/test/profile/Posix/gcov-dlopen.c b/compiler-rt/test/profile/Posix/gcov-dlopen.c index f09129d3b7c46..0212979e87ffd 100644 --- a/compiler-rt/test/profile/Posix/gcov-dlopen.c +++ b/compiler-rt/test/profile/Posix/gcov-dlopen.c @@ -64,14 +64,19 @@ int main(int argc, char *argv[]) { func3(); #endif - void (*gcov_flush1)() = (void (*)())dlsym(f1_handle, "__gcov_flush"); - if (gcov_flush1 == NULL) - return fprintf(stderr, "unable to find __gcov_flush in func1.so': %s\n", dlerror()); - void (*gcov_flush2)() = (void (*)())dlsym(f2_handle, "__gcov_flush"); - if (gcov_flush2 == NULL) - return fprintf(stderr, "unable to find __gcov_flush in func2.so': %s\n", dlerror()); - if (gcov_flush1 == gcov_flush2) - return fprintf(stderr, "same __gcov_flush found in func1.so and func2.so\n"); + void (*gcov_reset1)() = (void (*)())dlsym(f1_handle, "__gcov_reset"); + if (gcov_reset1 == NULL) + return fprintf(stderr, "unable to find __gcov_reset in func1.so': %s\n", dlerror()); + void (*gcov_reset2)() = (void (*)())dlsym(f2_handle, "__gcov_reset"); + if (gcov_reset2 == NULL) + return fprintf(stderr, "unable to find __gcov_reset in func2.so': %s\n", dlerror()); + if (gcov_reset1 == gcov_reset2) + return fprintf(stderr, "same __gcov_reset found in func1.so and func2.so\n"); + + /// Test that __gcov_dump is in the dynamic symbol table. + void (*gcov_dump1)() = (void (*)())dlsym(f1_handle, "__gcov_dump"); + if (gcov_dump1 == NULL) + return fprintf(stderr, "unable to find __gcov_dump in func1.so': %s\n", dlerror()); if (dlclose(f2_handle) != 0) return fprintf(stderr, "unable to close 'func2.so': %s\n", dlerror()); diff --git a/compiler-rt/test/profile/Posix/gcov-shared-flush.c b/compiler-rt/test/profile/Posix/gcov-shared-flush.c index 97d44ad5204e1..494fb9be761db 100644 --- a/compiler-rt/test/profile/Posix/gcov-shared-flush.c +++ b/compiler-rt/test/profile/Posix/gcov-shared-flush.c @@ -7,7 +7,7 @@ // RUN: %clang --coverage -fPIC -shared shared.c -o libfunc.so // RUN: test -f shared.gcno -/// Test the case where we exit abruptly after calling __gcov_flush, which means we don't write out the counters at exit. +/// Test the case where we exit abruptly after calling __gcov_dump, which means we don't write out the counters at exit. // RUN: %clang -DEXIT_ABRUPTLY -DSHARED_CALL_BEFORE_FLUSH -DSHARED_CALL_AFTER_FLUSH --coverage %s -L%t.d -rpath %t.d -lfunc -o %t // RUN: test -f gcov-shared-flush.gcno @@ -21,7 +21,7 @@ // SHARED: 1: {{[[0-9]+}}:void foo(int n) -/// Test the case where we exit normally and we have a call to the shared library function before __gcov_flush. +/// Test the case where we exit normally and we have a call to the shared library function before __gcov_dump. // RUN: %clang -DSHARED_CALL_BEFORE_FLUSH --coverage %s -L%t.d -rpath %t.d -lfunc -o %t // RUN: test -f gcov-shared-flush.gcno @@ -32,14 +32,15 @@ // BEFORE: -: {{[0-9]+}}:#ifdef SHARED_CALL_BEFORE_FLUSH // BEFORE-NEXT: 1: {{[0-9]+}}: foo(1); -// BEFORE: 1: {{[0-9]+}}: __gcov_flush(); +// BEFORE: 1: {{[0-9]+}}: __gcov_dump(); +// BEFORE-NEXT: 1: {{[0-9]+}}: __gcov_reset(); // BEFORE: -: {{[0-9]+}}:#ifdef SHARED_CALL_AFTER_FLUSH // BEFORE-NEXT: -: {{[0-9]+}}: foo(1); // BEFORE: 1: {{[0-9]+}}: bar(5); // SHARED_ONCE: 1: {{[0-9]+}}:void foo(int n) -// # Test the case where we exit normally and we have a call to the shared library function after __gcov_flush. +// # Test the case where we exit normally and we have a call to the shared library function after __gcov_dump. // RUN: %clang -DSHARED_CALL_AFTER_FLUSH --coverage %s -L%t.d -rpath %t.d -lfunc -o %t // RUN: test -f gcov-shared-flush.gcno @@ -50,12 +51,13 @@ // AFTER: -: {{[0-9]+}}:#ifdef SHARED_CALL_BEFORE_FLUSH // AFTER-NEXT: -: {{[0-9]+}}: foo(1); -// AFTER: 1: {{[0-9]+}}: __gcov_flush(); +// AFTER: 1: {{[0-9]+}}: __gcov_dump(); +// AFTER-NEXT: 1: {{[0-9]+}}: __gcov_reset(); // AFTER: -: {{[0-9]+}}:#ifdef SHARED_CALL_AFTER_FLUSH // AFTER-NEXT: 1: {{[0-9]+}}: foo(1); // AFTER: 1: {{[0-9]+}}: bar(5); -// # Test the case where we exit normally and we have calls to the shared library function before and after __gcov_flush. +// # Test the case where we exit normally and we have calls to the shared library function before and after __gcov_dump. // RUN: %clang -DSHARED_CALL_BEFORE_FLUSH -DSHARED_CALL_AFTER_FLUSH --coverage %s -L%t.d -rpath %t.d -lfunc -o %t // RUN: test -f gcov-shared-flush.gcno @@ -66,7 +68,8 @@ // BEFORE_AFTER: -: {{[0-9]+}}:#ifdef SHARED_CALL_BEFORE_FLUSH // BEFORE_AFTER-NEXT: 1: {{[0-9]+}}: foo(1); -// BEFORE_AFTER: 1: {{[0-9]+}}: __gcov_flush(); +// BEFORE_AFTER: 1: {{[0-9]+}}: __gcov_dump(); +// BEFORE_AFTER-NEXT: 1: {{[0-9]+}}: __gcov_reset(); // BEFORE_AFTER: -: {{[0-9]+}}:#ifdef SHARED_CALL_AFTER_FLUSH // BEFORE_AFTER-NEXT: 1: {{[0-9]+}}: foo(1); // BEFORE_AFTER: 1: {{[0-9]+}}: bar(5); @@ -78,7 +81,8 @@ void foo(int n) { } #else extern void foo(int n); -extern void __gcov_flush(void); +extern void __gcov_dump(void); +extern void __gcov_reset(void); int bar1 = 0; int bar2 = 1; @@ -96,7 +100,8 @@ int main(int argc, char *argv[]) { #endif bar(5); - __gcov_flush(); + __gcov_dump(); + __gcov_reset(); bar(5); #ifdef SHARED_CALL_AFTER_FLUSH diff --git a/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c b/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c index 5303e045063e8..649538dc2aaf1 100644 --- a/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c +++ b/compiler-rt/test/profile/gcov-__gcov_flush-terminate.c @@ -10,11 +10,13 @@ // CHECK: -: 0:Runs:1 // CHECK-NEXT: -: 0:Programs:1 -void __gcov_flush(void); +void __gcov_dump(void); +void __gcov_reset(void); int main(void) { // CHECK: 1: [[#@LINE]]:int main(void) int i = 22; // CHECK-NEXT: 1: [[#@LINE]]: - __gcov_flush(); // CHECK-NEXT: 1: [[#@LINE]]: + __gcov_dump(); // CHECK-NEXT: 1: [[#@LINE]]: + __gcov_reset(); // CHECK-NEXT: 1: [[#@LINE]]: i = 42; // CHECK-NEXT: 1: [[#@LINE]]: __builtin_trap(); // CHECK-NEXT: 1: [[#@LINE]]: i = 84; // CHECK-NEXT: 1: [[#@LINE]]: diff --git a/compiler-rt/test/profile/gcov-dump-and-remove.c b/compiler-rt/test/profile/gcov-dump-and-remove.c index 1dcf7b5bd5ca8..b7f80535aada3 100644 --- a/compiler-rt/test/profile/gcov-dump-and-remove.c +++ b/compiler-rt/test/profile/gcov-dump-and-remove.c @@ -8,16 +8,19 @@ // RUN: rm -f gcov-dump-and-remove.gcda && %run %t // RUN: llvm-cov gcov -t gcov-dump-and-remove.gcda | FileCheck %s -extern void __gcov_flush(void); +extern void __gcov_dump(void); +extern void __gcov_reset(void); extern int remove(const char *); // CHECK: -: [[#@LINE]]:extern int remove int main(void) { // CHECK-NEXT: #####: [[#@LINE]]: - __gcov_flush(); // CHECK-NEXT: #####: [[#@LINE]]: + __gcov_dump(); // CHECK-NEXT: #####: [[#@LINE]]: + __gcov_reset(); // CHECK-NEXT: #####: [[#@LINE]]: if (remove("gcov-dump-and-remove.gcda") != 0) // CHECK-NEXT: #####: [[#@LINE]]: return 1; // CHECK-NEXT: #####: [[#@LINE]]: return 1; // CHECK-NEXT: -: [[#@LINE]]: - __gcov_flush(); // CHECK-NEXT: #####: [[#@LINE]]: - __gcov_flush(); // CHECK-NEXT: #####: [[#@LINE]]: - if (remove("gcov-dump-and-remove.gcda") != 0) // CHECK-NEXT: #####: [[#@LINE]]: + __gcov_dump(); // CHECK-NEXT: 1: [[#@LINE]]: + __gcov_reset(); // CHECK-NEXT: 1: [[#@LINE]]: + __gcov_dump(); // CHECK-NEXT: 1: [[#@LINE]]: + if (remove("gcov-dump-and-remove.gcda") != 0) // CHECK-NEXT: 1: [[#@LINE]]: return 1; // CHECK-NEXT: #####: [[#@LINE]]: return 1; return 0; diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index d8a965a90127b..cd2ea8d5e4edd 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -130,7 +130,6 @@ class GCOVProfiler { Function * insertCounterWriteout(ArrayRef>); Function *insertReset(ArrayRef>); - Function *insertFlush(Function *ResetF); bool AddFlushBeforeForkAndExec(); @@ -909,7 +908,6 @@ bool GCOVProfiler::emitProfileArcs() { Function *WriteoutF = insertCounterWriteout(CountersBySP); Function *ResetF = insertReset(CountersBySP); - Function *FlushF = insertFlush(ResetF); // Create a small bit of code that registers the "__llvm_gcov_writeout" to // be executed at exit and the "__llvm_gcov_flush" function to be executed @@ -927,14 +925,13 @@ bool GCOVProfiler::emitProfileArcs() { IRBuilder<> Builder(BB); FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); - Type *Params[] = {PointerType::get(FTy, 0), PointerType::get(FTy, 0), - PointerType::get(FTy, 0)}; - FTy = FunctionType::get(Builder.getVoidTy(), Params, false); + auto *PFTy = PointerType::get(FTy, 0); + FTy = FunctionType::get(Builder.getVoidTy(), {PFTy, PFTy}, false); // Initialize the environment and register the local writeout, flush and // reset functions. FunctionCallee GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy); - Builder.CreateCall(GCOVInit, {WriteoutF, FlushF, ResetF}); + Builder.CreateCall(GCOVInit, {WriteoutF, ResetF}); Builder.CreateRetVoid(); appendToGlobalCtors(*M, F, 0); @@ -1266,36 +1263,3 @@ Function *GCOVProfiler::insertReset( return ResetF; } - -Function *GCOVProfiler::insertFlush(Function *ResetF) { - FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); - Function *FlushF = M->getFunction("__llvm_gcov_flush"); - if (!FlushF) - FlushF = Function::Create(FTy, GlobalValue::InternalLinkage, - "__llvm_gcov_flush", M); - FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); - FlushF->addFnAttr(Attribute::NoInline); - if (Options.NoRedZone) - FlushF->addFnAttr(Attribute::NoRedZone); - - BasicBlock *Entry = BasicBlock::Create(*Ctx, "entry", FlushF); - - // Write out the current counters. - Function *WriteoutF = M->getFunction("__llvm_gcov_writeout"); - assert(WriteoutF && "Need to create the writeout function first!"); - - IRBuilder<> Builder(Entry); - Builder.CreateCall(WriteoutF, {}); - Builder.CreateCall(ResetF, {}); - - Type *RetTy = FlushF->getReturnType(); - if (RetTy->isVoidTy()) - Builder.CreateRetVoid(); - else if (RetTy->isIntegerTy()) - // Used if __llvm_gcov_flush was implicitly declared. - Builder.CreateRet(ConstantInt::get(RetTy, 0)); - else - report_fatal_error("invalid return type for __llvm_gcov_flush"); - - return FlushF; -} From 1ee88e6efe4e578c064c2c3779ca104478dfe136 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Sat, 18 Jul 2020 22:21:29 +0000 Subject: [PATCH 738/771] Fix invalid link in the MLIR Standard Dialect www page (2nd attempt) --- mlir/include/mlir/Dialect/StandardOps/IR/Ops.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td index cde317065ffee..702b912d3103c 100644 --- a/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td +++ b/mlir/include/mlir/Dialect/StandardOps/IR/Ops.td @@ -1700,7 +1700,7 @@ def LoadOp : Std_Op<"load", In an `affine.if` or `affine.for` body, the indices of a load are restricted to SSA values bound to surrounding loop induction variables, - [symbols](AffineOps.md#dimensions-and-symbols), results of a + [symbols](Affine.md#dimensions-and-symbols), results of a [`constant` operation](#stdconstant-constantop), or the result of an `affine.apply` operation that can in turn take as arguments all of the aforementioned SSA values or the recursively result of such an From 3452a0d8c17f7166f479706b293caf6ac76ffd90 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 18 Jul 2020 20:26:01 -0700 Subject: [PATCH 739/771] [Driver] -B: don't search for target triple prefixes To match GCC (either crossing or not), which doesn't prepend target triple prefixes to `exec_prefixes`. As an example, powerpc64le-linux-gnu-gcc does not search "powerpc64le-linux-gnu-${name}" in a -B path. --- clang/lib/Driver/Driver.cpp | 8 +++----- clang/test/Driver/B-opt.c | 5 +++-- .../usr/bin/{armv7-windows-itanium-ld => ld} | 0 clang/test/Driver/fuse-ld.c | 8 +++----- clang/test/Driver/prefixed-tools.c | 4 ++-- clang/test/Driver/program-path-priority.c | 6 +++--- clang/test/Driver/windows-cross.c | 18 +++++++++--------- 7 files changed, 23 insertions(+), 26 deletions(-) rename clang/test/Driver/Inputs/Windows/ARM/8.1/usr/bin/{armv7-windows-itanium-ld => ld} (100%) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index d2b6268d5fa35..7d52882f85325 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -4785,8 +4785,7 @@ void Driver::generatePrefixedToolNames( Names.emplace_back((DefaultTargetTriple + "-" + Tool).str()); } -static bool ScanDirForExecutable(SmallString<128> &Dir, - const std::string &Name) { +static bool ScanDirForExecutable(SmallString<128> &Dir, StringRef Name) { llvm::sys::path::append(Dir, Name); if (llvm::sys::fs::can_execute(Twine(Dir))) return true; @@ -4803,9 +4802,8 @@ std::string Driver::GetProgramPath(StringRef Name, const ToolChain &TC) const { for (const auto &PrefixDir : PrefixDirs) { if (llvm::sys::fs::is_directory(PrefixDir)) { SmallString<128> P(PrefixDir); - for (const auto &TargetSpecificExecutable : TargetSpecificExecutables) - if (ScanDirForExecutable(P, TargetSpecificExecutable)) - return std::string(P.str()); + if (ScanDirForExecutable(P, Name)) + return std::string(P.str()); } else { SmallString<128> P((PrefixDir + Name).str()); if (llvm::sys::fs::can_execute(Twine(P))) diff --git a/clang/test/Driver/B-opt.c b/clang/test/Driver/B-opt.c index 5e5ff42fd0956..df85dee4b7040 100644 --- a/clang/test/Driver/B-opt.c +++ b/clang/test/Driver/B-opt.c @@ -1,9 +1,10 @@ // Check -B driver option. -// + +/// Target triple prefix is not detected for -B. // RUN: %clang %s -### -o %t.o -target i386-unknown-linux \ // RUN: -B %S/Inputs/B_opt_tree/dir1 -fuse-ld=ld 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-B-OPT-TRIPLE %s -// CHECK-B-OPT-TRIPLE: "{{.*}}/Inputs/B_opt_tree/dir1{{/|\\\\}}i386-unknown-linux-ld" +// CHECK-B-OPT-TRIPLE-NOT: "{{.*}}/Inputs/B_opt_tree/dir1{{/|\\\\}}i386-unknown-linux-ld" // // RUN: %clang %s -### -o %t.o -target i386-unknown-linux \ // RUN: -B %S/Inputs/B_opt_tree/dir2 -fuse-ld=ld 2>&1 \ diff --git a/clang/test/Driver/Inputs/Windows/ARM/8.1/usr/bin/armv7-windows-itanium-ld b/clang/test/Driver/Inputs/Windows/ARM/8.1/usr/bin/ld similarity index 100% rename from clang/test/Driver/Inputs/Windows/ARM/8.1/usr/bin/armv7-windows-itanium-ld rename to clang/test/Driver/Inputs/Windows/ARM/8.1/usr/bin/ld diff --git a/clang/test/Driver/fuse-ld.c b/clang/test/Driver/fuse-ld.c index 13e709ccfdfa4..f2ca9fb36194e 100644 --- a/clang/test/Driver/fuse-ld.c +++ b/clang/test/Driver/fuse-ld.c @@ -31,23 +31,21 @@ // RUN: | FileCheck %s -check-prefix=CHECK-FREEBSD-PLIB // CHECK-FREEBSD-PLIB: error: invalid linker name - - // RUN: %clang %s -### -fuse-ld=ld \ // RUN: -target arm-linux-androideabi \ -// RUN: -B%S/Inputs/basic_android_tree/bin 2>&1 \ +// RUN: -B%S/Inputs/basic_android_tree/bin/arm-linux-androideabi- 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-ANDROID-ARM-LD // CHECK-ANDROID-ARM-LD: Inputs/basic_android_tree/bin{{/|\\+}}arm-linux-androideabi-ld // RUN: %clang %s -### -fuse-ld=bfd \ // RUN: -target arm-linux-androideabi \ -// RUN: -B%S/Inputs/basic_android_tree/bin 2>&1 \ +// RUN: -B%S/Inputs/basic_android_tree/bin/arm-linux-androideabi- 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-ANDROID-ARM-BFD // CHECK-ANDROID-ARM-BFD: Inputs/basic_android_tree/bin{{/|\\+}}arm-linux-androideabi-ld.bfd // RUN: %clang %s -### -fuse-ld=gold \ // RUN: -target arm-linux-androideabi \ -// RUN: -B%S/Inputs/basic_android_tree/bin 2>&1 \ +// RUN: -B%S/Inputs/basic_android_tree/bin/arm-linux-androideabi- 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-ANDROID-ARM-GOLD // CHECK-ANDROID-ARM-GOLD: Inputs/basic_android_tree/bin{{/|\\+}}arm-linux-androideabi-ld.gold diff --git a/clang/test/Driver/prefixed-tools.c b/clang/test/Driver/prefixed-tools.c index 63f7f29ae9635..0252a2f701436 100644 --- a/clang/test/Driver/prefixed-tools.c +++ b/clang/test/Driver/prefixed-tools.c @@ -1,8 +1,8 @@ -// RUN: %clang -### -B%S/Inputs/prefixed_tools_tree -o %t.o -no-integrated-as -fuse-ld=ld \ +// RUN: %clang -### -B%S/Inputs/prefixed_tools_tree/x86_64--linux- -o %t.o -no-integrated-as -fuse-ld=ld \ // RUN: -target x86_64--linux %s 2>&1 | \ // RUN: FileCheck --check-prefix=CHECK-M64 %s -// RUN: %clang -### -B%S/Inputs/prefixed_tools_tree -o %t.o -no-integrated-as -fuse-ld=ld \ +// RUN: %clang -### -B%S/Inputs/prefixed_tools_tree/x86_64--linux- -o %t.o -no-integrated-as -fuse-ld=ld \ // RUN: -m32 -target x86_64--linux %s 2>&1 | \ // RUN: FileCheck --check-prefix=CHECK-M32 %s diff --git a/clang/test/Driver/program-path-priority.c b/clang/test/Driver/program-path-priority.c index 9f1109f530c65..cba5f9f4d7430 100644 --- a/clang/test/Driver/program-path-priority.c +++ b/clang/test/Driver/program-path-priority.c @@ -119,15 +119,15 @@ // RUN: test -f %t/%target_triple-gcc && \ // RUN: mv %t/%target_triple-gcc %t/prefix || true // RUN: touch %t/notreal-none-elf-gcc && chmod +x %t/notreal-none-elf-gcc +// RUN: touch %t/prefix/gcc && chmod +x %t/prefix/gcc // RUN: env "PATH=" %t/clang -### -target notreal-none-elf %s -B %t/prefix 2>&1 | \ // RUN: FileCheck --check-prefix=DEFAULT_TRIPLE_IN_PREFIX %s -// DEFAULT_TRIPLE_IN_PREFIX: prefix/{{.*}}-gcc" +// DEFAULT_TRIPLE_IN_PREFIX: prefix/gcc" // DEFAULT_TRIPLE_IN_PREFIX-NOT: notreal-none-elf-gcc" /// Only if there is nothing in the prefix will we search other paths /// -f in case $DEFAULT_TRIPLE == %target_triple -// RUN: rm -f %t/prefix/$DEFAULT_TRIPLE-gcc -// RUN: rm -f %t/prefix/%target_triple-gcc +// RUN: rm -f %t/prefix/$DEFAULT_TRIPLE-gcc %t/prefix/%target_triple-gcc %t/prefix/gcc // RUN: env "PATH=" %t/clang -### -target notreal-none-elf %s -B %t/prefix 2>&1 | \ // RUN: FileCheck --check-prefix=EMPTY_PREFIX_DIR %s // EMPTY_PREFIX_DIR: notreal-none-elf-gcc" diff --git a/clang/test/Driver/windows-cross.c b/clang/test/Driver/windows-cross.c index d96b0283a90ec..96497da61c0d5 100644 --- a/clang/test/Driver/windows-cross.c +++ b/clang/test/Driver/windows-cross.c @@ -1,47 +1,47 @@ // RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -stdlib=libstdc++ -rtlib=compiler-rt -o /dev/null %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-BASIC-LIBCXX -// CHECK-BASIC-LIBCXX: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{[^"]*}}.o" "-lmsvcrt" +// CHECK-BASIC-LIBCXX: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{[^"]*}}.o" "-lmsvcrt" // RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -stdlib=libstdc++ -rtlib=compiler-rt -static -o /dev/null %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-STATIC -// CHECK-STATIC: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bstatic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{[^"]*}}.o" "-lmsvcrt" +// CHECK-STATIC: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bstatic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{[^"]*}}.o" "-lmsvcrt" // RUN: %clang -### -target armv7-windows-itanium --sysroot %s/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -rtlib=compiler-rt -stdlib=libstdc++ -o /dev/null %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-RTLIB -// CHECK-RTLIB: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" +// CHECK-RTLIB: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" // RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -rtlib=compiler-rt -stdlib=libc++ -o /dev/null %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-C-LIBCXX -// CHECK-C-LIBCXX: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" +// CHECK-C-LIBCXX: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" // RUN: %clangxx -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -rtlib=compiler-rt -stdlib=libc++ -o /dev/null %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-LIBCXX -// CHECK-LIBCXX: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{.*}}.o" "-lc++" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" +// CHECK-LIBCXX: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-Bdynamic" "--entry" "mainCRTStartup" "--allow-multiple-definition" "-o" "{{[^"]*}}" "{{.*}}.o" "-lc++" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" // RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -shared -rtlib=compiler-rt -stdlib=libc++ -o shared.dll %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-SHARED -// CHECK-SHARED: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bdynamic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" +// CHECK-SHARED: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bdynamic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" // RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -shared -rtlib=compiler-rt -stdlib=libc++ -static -o shared.dll %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-SHARED-STATIC -// CHECK-SHARED-STATIC: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bstatic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" +// CHECK-SHARED-STATIC: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bstatic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" // RUN: %clang -### -target armv7-windows-itanium --sysroot %s/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -shared -rtlib=compiler-rt -stdlib=libc++ -nostartfiles -o shared.dll %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-NOSTARTFILES -// CHECK-NOSTARTFILES: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bdynamic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" +// CHECK-NOSTARTFILES: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bdynamic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" "-lmsvcrt" "{{.*[\\/]}}clang_rt.builtins-arm.lib" // RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=ld -shared -rtlib=compiler-rt -stdlib=libc++ -nostartfiles -nodefaultlibs -o shared.dll %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-STANDALONE -// CHECK-STANDALONE: armv7-windows-itanium-ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bdynamic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" +// CHECK-STANDALONE: {{[/\\]}}ld" "--sysroot={{.*}}/Inputs/Windows/ARM/8.1" "-m" "thumb2pe" "-shared" "-Bdynamic" "--enable-auto-image-base" "--entry" "_DllMainCRTStartup" "--allow-multiple-definition" "-o" "shared.dll" "--out-implib" "shared.lib" "{{.*}}.o" // RUN: %clang -### -target armv7-windows-itanium --sysroot %S/Inputs/Windows/ARM/8.1 -B %S/Inputs/Windows/ARM/8.1/usr/bin -fuse-ld=lld-link2 -shared -o shared.dll -x c++ %s 2>&1 \ // RUN: | FileCheck %s --check-prefix CHECK-FUSE-LD From b2b39c5d455b950c6fffcc902924516fe7f8ec9f Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sat, 18 Jul 2020 21:01:41 -0700 Subject: [PATCH 740/771] [Driver] --print-search-dirs: print -B options and COMPILER_PATH --- clang/lib/Driver/Driver.cpp | 7 +++++++ clang/test/Driver/immediate-options.c | 4 ---- clang/test/Driver/print-search-dirs.c | 6 ++++++ 3 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 clang/test/Driver/print-search-dirs.c diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 7d52882f85325..317098e248233 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1748,6 +1748,13 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { if (C.getArgs().hasArg(options::OPT_print_search_dirs)) { llvm::outs() << "programs: ="; bool separator = false; + // Print -B and COMPILER_PATH. + for (const std::string &Path : PrefixDirs) { + if (separator) + llvm::outs() << llvm::sys::EnvPathSeparator; + llvm::outs() << Path; + separator = true; + } for (const std::string &Path : TC.getProgramPaths()) { if (separator) llvm::outs() << llvm::sys::EnvPathSeparator; diff --git a/clang/test/Driver/immediate-options.c b/clang/test/Driver/immediate-options.c index 71494eec616f9..d7cd6be408016 100644 --- a/clang/test/Driver/immediate-options.c +++ b/clang/test/Driver/immediate-options.c @@ -9,10 +9,6 @@ // RUN: %clang -dumpversion | FileCheck %s -check-prefix=DUMPVERSION // DUMPVERSION: {{[0-9]+\.[0-9.]+}} -// RUN: %clang -print-search-dirs | FileCheck %s -check-prefix=PRINT-SEARCH-DIRS -// PRINT-SEARCH-DIRS: programs: ={{.*}} -// PRINT-SEARCH-DIRS: libraries: ={{.*}} - // Test if the -print-resource-dir option is accepted without error. // Allow unspecified output because the value of CLANG_RESOURCE_DIR is unknown. // RUN: %clang -print-resource-dir | FileCheck %s -check-prefix=PRINT-RESOURCE-DIR diff --git a/clang/test/Driver/print-search-dirs.c b/clang/test/Driver/print-search-dirs.c new file mode 100644 index 0000000000000..0ac13125c9a13 --- /dev/null +++ b/clang/test/Driver/print-search-dirs.c @@ -0,0 +1,6 @@ +// UNSUPPORTED: system-windows + +// RUN: env COMPILER_PATH=cpath1:cpath2 %clang %s -target x86_64-pc-freebsd --sysroot=%S/Inputs/basic_freebsd64_tree \ +// RUN: -B b1 -B b2 -print-search-dirs | FileCheck %s +// CHECK: programs: =b1:b2:cpath1:cpath2:{{.*}} +// CHECK-NEXT: libraries: ={{.*}}Inputs/basic_freebsd64_tree/usr/lib From 606e756bb10a52318bece68a8b844e06ce71641d Mon Sep 17 00:00:00 2001 From: Yuanfang Chen Date: Sat, 18 Jul 2020 22:26:37 -0700 Subject: [PATCH 741/771] [NewPM] make parsePassPipeline parse adaptor-wrapped user passes Currently, when parsing text pipeline, different kinds of passes always introduce nested pass managers. This makes it impossible to test the adaptor-wrapped user passes from the text pipeline interface which is needed by D82344 test cases. This also seems useful in general. See comments above `parsePassPipeline`. The syntax would be like mixing passes of different types, but it is not the same as inferring the correct pass type and then adding the matching nested pass managers. Strictly speaking, the resulted pipelines are different. Reviewed By: asbirlea, aeubanks Differential Revision: https://reviews.llvm.org/D82698 --- llvm/include/llvm/Passes/PassBuilder.h | 19 ++++-- llvm/lib/Passes/PassBuilder.cpp | 82 ++++++++++++++++++++++++ llvm/test/Other/pass-pipeline-parsing.ll | 31 +++++++++ 3 files changed, 128 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/Passes/PassBuilder.h b/llvm/include/llvm/Passes/PassBuilder.h index 0357e4a2fc058..b0703457656b2 100644 --- a/llvm/include/llvm/Passes/PassBuilder.h +++ b/llvm/include/llvm/Passes/PassBuilder.h @@ -472,10 +472,21 @@ class PassBuilder { /// module(function(loop(lpass1,lpass2,lpass3))) /// /// This shortcut is especially useful for debugging and testing small pass - /// combinations. Note that these shortcuts don't introduce any other magic. - /// If the sequence of passes aren't all the exact same kind of pass, it will - /// be an error. You cannot mix different levels implicitly, you must - /// explicitly form a pass manager in which to nest passes. + /// combinations. + /// + /// The sequence of passes aren't necessarily the exact same kind of pass. + /// You can mix different levels implicitly if adaptor passes are defined to + /// make them work. For example, + /// + /// mpass1,fpass1,fpass2,mpass2,lpass1 + /// + /// This pipeline uses only one pass manager: the top-level module manager. + /// fpass1,fpass2 and lpass1 are added into the the top-level module manager + /// using only adaptor passes. No nested function/loop pass managers are + /// added. The purpose is to allow easy pass testing when the user + /// specifically want the pass to run under a adaptor directly. This is + /// preferred when a pipeline is largely of one type, but one or just a few + /// passes are of different types(See PassBuilder.cpp for examples). Error parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, bool VerifyEachPass = true, bool DebugLogging = false); diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 4db7bebcb77ce..1766e579c33d6 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -2212,6 +2212,40 @@ Error PassBuilder::parseModulePass(ModulePassManager &MPM, std::remove_reference::type>()); \ return Error::success(); \ } +#define CGSCC_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } +#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + MPM.addPass(createModuleToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \ + return Error::success(); \ + } +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + MPM.addPass(createModuleToFunctionPassAdaptor( \ + createFunctionToLoopPassAdaptor(CREATE_PASS, false, DebugLogging))); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + MPM.addPass( \ + createModuleToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \ + CREATE_PASS(Params.get()), false, DebugLogging))); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : ModulePipelineParsingCallbacks) @@ -2295,6 +2329,35 @@ Error PassBuilder::parseCGSCCPass(CGSCCPassManager &CGPM, std::remove_reference::type>()); \ return Error::success(); \ } +#define FUNCTION_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS)); \ + return Error::success(); \ + } +#define FUNCTION_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + CGPM.addPass(createCGSCCToFunctionPassAdaptor(CREATE_PASS(Params.get()))); \ + return Error::success(); \ + } +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + CGPM.addPass(createCGSCCToFunctionPassAdaptor( \ + createFunctionToLoopPassAdaptor(CREATE_PASS, false, DebugLogging))); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + CGPM.addPass( \ + createCGSCCToFunctionPassAdaptor(createFunctionToLoopPassAdaptor( \ + CREATE_PASS(Params.get()), false, DebugLogging))); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : CGSCCPipelineParsingCallbacks) @@ -2378,6 +2441,25 @@ Error PassBuilder::parseFunctionPass(FunctionPassManager &FPM, std::remove_reference::type>()); \ return Error::success(); \ } +// FIXME: UseMemorySSA is set to false. Maybe we could do things like: +// bool UseMemorySSA = !("canon-freeze" || "loop-predication" || +// "guard-widening"); +// The risk is that it may become obsolete if we're not careful. +#define LOOP_PASS(NAME, CREATE_PASS) \ + if (Name == NAME) { \ + FPM.addPass( \ + createFunctionToLoopPassAdaptor(CREATE_PASS, false, DebugLogging)); \ + return Error::success(); \ + } +#define LOOP_PASS_WITH_PARAMS(NAME, CREATE_PASS, PARSER) \ + if (checkParametrizedPassName(Name, NAME)) { \ + auto Params = parsePassParameters(PARSER, Name, NAME); \ + if (!Params) \ + return Params.takeError(); \ + FPM.addPass(createFunctionToLoopPassAdaptor(CREATE_PASS(Params.get()), \ + false, DebugLogging)); \ + return Error::success(); \ + } #include "PassRegistry.def" for (auto &C : FunctionPipelineParsingCallbacks) diff --git a/llvm/test/Other/pass-pipeline-parsing.ll b/llvm/test/Other/pass-pipeline-parsing.ll index 2e8bc7c873025..902bd9b3eabb1 100644 --- a/llvm/test/Other/pass-pipeline-parsing.ll +++ b/llvm/test/Other/pass-pipeline-parsing.ll @@ -173,6 +173,37 @@ ; CHECK-NESTED-FP-LP: Finished llvm::Function pass manager run ; CHECK-NESTED-FP-LP: Finished llvm::Module pass manager run +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='module(no-op-function,no-op-loop,no-op-cgscc,cgscc(no-op-function,no-op-loop),function(no-op-loop))' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-ADAPTORS +; CHECK-ADAPTORS: Starting llvm::Module pass manager run +; CHECK-ADAPTORS: Starting llvm::Module pass manager run +; CHECK-ADAPTORS: Running pass: ModuleToFunctionPassAdaptor<{{.*}}NoOpFunctionPass> +; CHECK-ADAPTORS: Running pass: ModuleToFunctionPassAdaptor<{{.*}}FunctionToLoopPassAdaptor<{{.*}}NoOpLoopPass>{{.*}}> +; CHECK-ADAPTORS: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}NoOpCGSCCPass> +; CHECK-ADAPTORS: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}LazyCallGraph{{.*}}> +; CHECK-ADAPTORS: Starting CGSCC pass manager run +; CHECK-ADAPTORS: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}NoOpFunctionPass> +; CHECK-ADAPTORS: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}FunctionToLoopPassAdaptor<{{.*}}NoOpLoopPass>{{.*}}> +; CHECK-ADAPTORS: Finished CGSCC pass manager run +; CHECK-ADAPTORS: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}> +; CHECK-ADAPTORS: Starting llvm::Function pass manager run +; CHECK-ADAPTORS: Running pass: FunctionToLoopPassAdaptor<{{.*}}NoOpLoopPass> +; CHECK-ADAPTORS: Finished llvm::Function pass manager run +; CHECK-ADAPTORS: Finished llvm::Module pass manager run +; CHECK-ADAPTORS: Finished llvm::Module pass manager run + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='cgscc(print)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-PRINT-IN-CGSCC +; CHECK-PRINT-IN-CGSCC: Starting llvm::Module pass manager run +; CHECK-PRINT-IN-CGSCC: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}LazyCallGraph{{.*}}> +; CHECK-PRINT-IN-CGSCC: Starting CGSCC pass manager run +; CHECK-PRINT-IN-CGSCC: Running pass: CGSCCToFunctionPassAdaptor<{{.*}}PrintFunctionPass> +; CHECK-PRINT-IN-CGSCC: Finished CGSCC pass manager run +; CHECK-PRINT-IN-CGSCC: Running pass: VerifierPass +; CHECK-PRINT-IN-CGSCC: Finished llvm::Module pass manager run + ; RUN: not opt -disable-output -debug-pass-manager \ ; RUN: -passes='function(no-op-function)function(no-op-function)' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-MISSING-COMMA1 From af4c8730924fb6617494c223dac62d6c72c97c6f Mon Sep 17 00:00:00 2001 From: Yuanfang Chen Date: Sat, 18 Jul 2020 22:23:07 -0700 Subject: [PATCH 742/771] [NewPM] Allow passes to never be skipped A pass declares itself unskippable by defining a method `static bool isRequired()`. Also, this patch makes pass managers and adaptor passes required (unskippable). PassInstrumentation before-pass-callbacks could be used to skip passes by returning false. However, some passes should not be skipped at all. Especially so for special-purpose passes such as pass managers and adaptor passes since if they are skipped for any reason, the passes contained by them would also be skipped ignoring contained passes's return value of `isRequired()`. Reviewed By: aeubanks Differential Revision: https://reviews.llvm.org/D82344 --- llvm/include/llvm/Analysis/CGSCCPassManager.h | 4 ++ llvm/include/llvm/IR/PassInstrumentation.h | 21 +++++++ llvm/include/llvm/IR/PassManager.h | 4 ++ llvm/include/llvm/IR/PassManagerInternal.h | 22 +++++++ .../llvm/Transforms/Scalar/LoopPassManager.h | 2 + .../unittests/IR/PassBuilderCallbacksTest.cpp | 63 +++++++++++++++++-- 6 files changed, 111 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/Analysis/CGSCCPassManager.h b/llvm/include/llvm/Analysis/CGSCCPassManager.h index eb0d3ae8fedfc..e70af71b3da67 100644 --- a/llvm/include/llvm/Analysis/CGSCCPassManager.h +++ b/llvm/include/llvm/Analysis/CGSCCPassManager.h @@ -355,6 +355,8 @@ class ModuleToPostOrderCGSCCPassAdaptor /// Runs the CGSCC pass across every SCC in the module. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); + static bool isRequired() { return true; } + private: CGSCCPassT Pass; }; @@ -543,6 +545,8 @@ class CGSCCToFunctionPassAdaptor return PA; } + static bool isRequired() { return true; } + private: FunctionPassT Pass; }; diff --git a/llvm/include/llvm/IR/PassInstrumentation.h b/llvm/include/llvm/IR/PassInstrumentation.h index bcc434548e670..37390e4e682ba 100644 --- a/llvm/include/llvm/IR/PassInstrumentation.h +++ b/llvm/include/llvm/IR/PassInstrumentation.h @@ -129,6 +129,26 @@ class PassInstrumentationCallbacks { class PassInstrumentation { PassInstrumentationCallbacks *Callbacks; + // Template argument PassT of PassInstrumentation::runBeforePass could be two + // kinds: (1) a regular pass inherited from PassInfoMixin (happen when + // creating a adaptor pass for a regular pass); (2) a type-erased PassConcept + // created from (1). Here we want to make case (1) skippable unconditionally + // since they are regular passes. We call PassConcept::isRequired to decide + // for case (2). + template + using has_required_t = decltype(std::declval().isRequired()); + + template + static std::enable_if_t::value, bool> + isRequired(const PassT &Pass) { + return Pass.isRequired(); + } + template + static std::enable_if_t::value, bool> + isRequired(const PassT &Pass) { + return false; + } + public: /// Callbacks object is not owned by PassInstrumentation, its life-time /// should at least match the life-time of corresponding @@ -148,6 +168,7 @@ class PassInstrumentation { bool ShouldRun = true; for (auto &C : Callbacks->BeforePassCallbacks) ShouldRun &= C(Pass.name(), llvm::Any(&IR)); + ShouldRun = ShouldRun || isRequired(Pass); return ShouldRun; } diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h index 4d5f292ba9a13..f503871e23609 100644 --- a/llvm/include/llvm/IR/PassManager.h +++ b/llvm/include/llvm/IR/PassManager.h @@ -559,6 +559,8 @@ class PassManager : public PassInfoMixin< Passes.emplace_back(new PassModelT(std::move(Pass))); } + static bool isRequired() { return true; } + private: using PassConceptT = detail::PassConcept; @@ -1260,6 +1262,8 @@ class ModuleToFunctionPassAdaptor return PA; } + static bool isRequired() { return true; } + private: FunctionPassT Pass; }; diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h index c602c0b5cc20a..986ed0b5a7ac6 100644 --- a/llvm/include/llvm/IR/PassManagerInternal.h +++ b/llvm/include/llvm/IR/PassManagerInternal.h @@ -48,6 +48,12 @@ struct PassConcept { /// Polymorphic method to access the name of a pass. virtual StringRef name() const = 0; + + /// Polymorphic method to to let a pass optionally exempted from skipping by + /// PassInstrumentation. + /// To opt-in, pass should implement `static bool isRequired()`. It's no-op + /// to have `isRequired` always return false since that is the default. + virtual bool isRequired() const = 0; }; /// A template wrapper used to implement the polymorphic API. @@ -81,6 +87,22 @@ struct PassModel : PassConcept { StringRef name() const override { return PassT::name(); } + template + using has_required_t = decltype(std::declval().isRequired()); + + template + static std::enable_if_t::value, bool> + passIsRequiredImpl() { + return T::isRequired(); + } + template + static std::enable_if_t::value, bool> + passIsRequiredImpl() { + return false; + } + + bool isRequired() const override { return passIsRequiredImpl(); } + PassT Pass; }; diff --git a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h index 9b2f0fcab95be..aff80ef1dcfab 100644 --- a/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h +++ b/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h @@ -366,6 +366,8 @@ class FunctionToLoopPassAdaptor return PA; } + static bool isRequired() { return true; } + private: LoopPassT Pass; diff --git a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp index 1f17a4f34b18e..c2c15069f4132 100644 --- a/llvm/unittests/IR/PassBuilderCallbacksTest.cpp +++ b/llvm/unittests/IR/PassBuilderCallbacksTest.cpp @@ -524,10 +524,10 @@ TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) { // Non-mock instrumentation run here can safely be ignored. CallbacksHandle.ignoreNonMockPassInstrumentation(""); - // Skip the pass by returning false. - EXPECT_CALL(CallbacksHandle, runBeforePass(HasNameRegex("MockPassHandle"), - HasName(""))) - .WillOnce(Return(false)); + // Skip all passes by returning false. Pass managers and adaptor passes are + // also passes that observed by the callbacks. + EXPECT_CALL(CallbacksHandle, runBeforePass(_, _)) + .WillRepeatedly(Return(false)); EXPECT_CALL(AnalysisHandle, run(HasName(""), _)).Times(0); EXPECT_CALL(PassHandle, run(HasName(""), _)).Times(0); @@ -543,7 +543,60 @@ TEST_F(ModuleCallbacksTest, InstrumentedSkippedPasses) { runAfterAnalysis(HasNameRegex("MockAnalysisHandle"), _)) .Times(0); - StringRef PipelineText = "test-transform"; + // Order is important here. `Adaptor` expectations should be checked first + // because the its argument contains 'PassManager' (for example: + // ModuleToFunctionPassAdaptor{{.*}}PassManager{{.*}}). Here only check + // `runAfterPass` to show that they are not skipped. + + // Pass managers are not ignored. + // 5 = (1) ModulePassManager + (2) FunctionPassMangers + (1) LoopPassManager + + // (1) CGSCCPassManager + EXPECT_CALL(CallbacksHandle, runAfterPass(HasNameRegex("PassManager"), _)) + .Times(5); + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("ModuleToFunctionPassAdaptor"), _)) + .Times(1); + EXPECT_CALL( + CallbacksHandle, + runAfterPass(HasNameRegex("ModuleToPostOrderCGSCCPassAdaptor"), _)) + .Times(1); + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("CGSCCToFunctionPassAdaptor"), _)) + .Times(1); + EXPECT_CALL(CallbacksHandle, + runAfterPass(HasNameRegex("FunctionToLoopPassAdaptor"), _)) + .Times(1); + + // Ignore analyses introduced by adaptor passes. + EXPECT_CALL(CallbacksHandle, + runBeforeAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _)) + .Times(AnyNumber()); + EXPECT_CALL(CallbacksHandle, + runAfterAnalysis(Not(HasNameRegex("MockAnalysisHandle")), _)) + .Times(AnyNumber()); + + // Register Funtion and Loop version of "test-transform" for testing + PB.registerPipelineParsingCallback( + [](StringRef Name, FunctionPassManager &FPM, + ArrayRef) { + if (Name == "test-transform") { + FPM.addPass(MockPassHandle().getPass()); + return true; + } + return false; + }); + PB.registerPipelineParsingCallback( + [](StringRef Name, LoopPassManager &LPM, + ArrayRef) { + if (Name == "test-transform") { + LPM.addPass(MockPassHandle().getPass()); + return true; + } + return false; + }); + + StringRef PipelineText = "test-transform,function(test-transform),cgscc(" + "function(loop(test-transform)))"; ASSERT_THAT_ERROR(PB.parsePassPipeline(PM, PipelineText, true), Succeeded()) << "Pipeline was: " << PipelineText; From d37befdfe5cd93666f8077c32836673ad70385d1 Mon Sep 17 00:00:00 2001 From: Kang Zhang Date: Sun, 19 Jul 2020 07:01:45 +0000 Subject: [PATCH 743/771] [PowerPC] Remove the redundant implicit operands in ppc-early-ret pass Summary: In the `ppc-early-ret` pass, we have use `BuildMI` and `copyImplicitOps` when the branch instructions can do the early return. But the two functions will add implicit operands twice, this is not correct. This patch is to remove the redundant implicit operands in `ppc-early-ret pass`. Reviewed By: jsji Differential Revision: https://reviews.llvm.org/D76042 --- llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp | 26 ++++++++++++------- .../test/CodeGen/PowerPC/early-ret-verify.mir | 2 +- llvm/test/CodeGen/PowerPC/early-ret.mir | 8 +++--- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp b/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp index c9f74bbf861ca..08b7bdb3ac1e2 100644 --- a/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp +++ b/llvm/lib/Target/PowerPC/PPCEarlyReturn.cpp @@ -77,8 +77,9 @@ namespace { if (J->getOperand(0).getMBB() == &ReturnMBB) { // This is an unconditional branch to the return. Replace the // branch with a blr. - BuildMI(**PI, J, J->getDebugLoc(), TII->get(I->getOpcode())) - .copyImplicitOps(*I); + MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I); + (*PI)->insert(J, MI); + MachineBasicBlock::iterator K = J--; K->eraseFromParent(); BlockChanged = true; @@ -89,10 +90,13 @@ namespace { if (J->getOperand(2).getMBB() == &ReturnMBB) { // This is a conditional branch to the return. Replace the branch // with a bclr. - BuildMI(**PI, J, J->getDebugLoc(), TII->get(PPC::BCCLR)) + MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I); + MI->setDesc(TII->get(PPC::BCCLR)); + MachineInstrBuilder(*ReturnMBB.getParent(), MI) .add(J->getOperand(0)) - .add(J->getOperand(1)) - .copyImplicitOps(*I); + .add(J->getOperand(1)); + (*PI)->insert(J, MI); + MachineBasicBlock::iterator K = J--; K->eraseFromParent(); BlockChanged = true; @@ -103,11 +107,13 @@ namespace { if (J->getOperand(1).getMBB() == &ReturnMBB) { // This is a conditional branch to the return. Replace the branch // with a bclr. - BuildMI( - **PI, J, J->getDebugLoc(), - TII->get(J->getOpcode() == PPC::BC ? PPC::BCLR : PPC::BCLRn)) - .add(J->getOperand(0)) - .copyImplicitOps(*I); + MachineInstr *MI = ReturnMBB.getParent()->CloneMachineInstr(&*I); + MI->setDesc( + TII->get(J->getOpcode() == PPC::BC ? PPC::BCLR : PPC::BCLRn)); + MachineInstrBuilder(*ReturnMBB.getParent(), MI) + .add(J->getOperand(0)); + (*PI)->insert(J, MI); + MachineBasicBlock::iterator K = J--; K->eraseFromParent(); BlockChanged = true; diff --git a/llvm/test/CodeGen/PowerPC/early-ret-verify.mir b/llvm/test/CodeGen/PowerPC/early-ret-verify.mir index 5a01aa4effa5a..967e53302607f 100644 --- a/llvm/test/CodeGen/PowerPC/early-ret-verify.mir +++ b/llvm/test/CodeGen/PowerPC/early-ret-verify.mir @@ -40,7 +40,7 @@ body: | ; CHECK-LABEL: testEarlyRet ; CHECK: bb.0.entry: - ; CHECK: BCLR undef renamable $cr5lt, implicit $lr, implicit $rm, implicit $lr, implicit $rm + ; CHECK: BCLR undef renamable $cr5lt, implicit $lr, implicit $rm ; CHECK: bb.1: ; CHECK: renamable $r3 = IMPLICIT_DEF ; CHECK: renamable $r4 = IMPLICIT_DEF diff --git a/llvm/test/CodeGen/PowerPC/early-ret.mir b/llvm/test/CodeGen/PowerPC/early-ret.mir index bfbaa8edeb972..9bc97695bb65c 100644 --- a/llvm/test/CodeGen/PowerPC/early-ret.mir +++ b/llvm/test/CodeGen/PowerPC/early-ret.mir @@ -27,7 +27,7 @@ body: | ; CHECK: bb.0.entry: ; CHECK: renamable $cr0 = CMPWI renamable $r3, 0 ; CHECK: BC killed renamable $cr0gt, %bb.1 - ; CHECK: BLR implicit $lr, implicit $rm, implicit $lr, implicit $rm, implicit killed $r3 + ; CHECK: BLR implicit $lr, implicit $rm, implicit killed $r3 ; CHECK: bb.1.entry: ; CHECK: renamable $r3 = ADDI killed renamable $r4, 0 ; CHECK: BLR implicit $lr, implicit $rm, implicit killed $r3 @@ -106,7 +106,7 @@ body: | ; CHECK-LABEL: name: testBCLR ; CHECK: bb.0.entry: ; CHECK: renamable $cr0 = FCMPUS killed renamable $f3, killed renamable $f4 - ; CHECK: BCLR killed renamable $cr0eq, implicit $lr, implicit $rm, implicit $lr, implicit $rm, implicit killed $v2 + ; CHECK: BCLR killed renamable $cr0eq, implicit $lr, implicit $rm, implicit killed $v2 ; CHECK: bb.1.entry: ; CHECK: renamable $cr0 = FCMPUS killed renamable $f1, killed renamable $f2 ; CHECK: BCLRn killed renamable $cr0eq, implicit $lr, implicit $rm, implicit killed $v2 @@ -139,8 +139,8 @@ body: | ; CHECK: bb.0.entry: ; CHECK: renamable $r4 = LI 0 ; CHECK: renamable $cr0 = CMPLWI killed renamable $r4, 0 - ; CHECK: BCCLR 68, renamable $cr0, implicit $lr, implicit $rm, implicit $lr, implicit $rm + ; CHECK: BCCLR 68, renamable $cr0, implicit $lr, implicit $rm ; CHECK: bb.1: - ; CHECK: BCCLR 68, killed renamable $cr0, implicit $lr, implicit $rm, implicit $lr, implicit $rm + ; CHECK: BCCLR 68, killed renamable $cr0, implicit $lr, implicit $rm ; CHECK: BLR implicit $lr, implicit $rm ... From 2e74b6d80f347203ae17ec8b09e6b3e86ff6c179 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Sun, 19 Jul 2020 00:26:01 -0700 Subject: [PATCH 744/771] [llvm-cov gcov] Don't require NUL terminator when reading files .gcno, .gcda and source files can be modified while we are reading them. If the concurrent modification of a file being read nullifies the NUL terminator assumption, llvm-cov can trip over an assertion failure in MemoryBuffer::init. This is not so rare - the source files can be in an editor and .gcda can be written by an running process (if the process forks, when .gcda gets written is probably more unpredictable). There is no accompanying test because an assertion failure requires data races with some involved setting. --- llvm/lib/ProfileData/GCOV.cpp | 5 ++++- llvm/tools/llvm-cov/gcov.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/llvm/lib/ProfileData/GCOV.cpp b/llvm/lib/ProfileData/GCOV.cpp index 71ea44a1a722d..7b97723da60cc 100644 --- a/llvm/lib/ProfileData/GCOV.cpp +++ b/llvm/lib/ProfileData/GCOV.cpp @@ -522,8 +522,11 @@ class LineConsumer { public: LineConsumer() = default; LineConsumer(StringRef Filename) { + // Open source files without requiring a NUL terminator. The concurrent + // modification may nullify the NUL terminator condition. ErrorOr> BufferOrErr = - MemoryBuffer::getFileOrSTDIN(Filename); + MemoryBuffer::getFileOrSTDIN(Filename, -1, + /*RequiresNullTerminator=*/false); if (std::error_code EC = BufferOrErr.getError()) { errs() << Filename << ": " << EC.message() << "\n"; Remaining = ""; diff --git a/llvm/tools/llvm-cov/gcov.cpp b/llvm/tools/llvm-cov/gcov.cpp index 7a1dbbfe9338b..d99e792c68a95 100644 --- a/llvm/tools/llvm-cov/gcov.cpp +++ b/llvm/tools/llvm-cov/gcov.cpp @@ -43,8 +43,10 @@ static void reportCoverage(StringRef SourceFile, StringRef ObjectDir, : InputGCDA; GCOVFile GF; + // Open .gcda and .gcda without requiring a NUL terminator. The concurrent + // modification may nullify the NUL terminator condition. ErrorOr> GCNO_Buff = - MemoryBuffer::getFileOrSTDIN(GCNO); + MemoryBuffer::getFileOrSTDIN(GCNO, -1, /*RequiresNullTerminator=*/false); if (std::error_code EC = GCNO_Buff.getError()) { errs() << GCNO << ": " << EC.message() << "\n"; return; @@ -56,7 +58,7 @@ static void reportCoverage(StringRef SourceFile, StringRef ObjectDir, } ErrorOr> GCDA_Buff = - MemoryBuffer::getFileOrSTDIN(GCDA); + MemoryBuffer::getFileOrSTDIN(GCDA, -1, /*RequiresNullTerminator=*/false); if (std::error_code EC = GCDA_Buff.getError()) { if (EC != errc::no_such_file_or_directory) { errs() << GCDA << ": " << EC.message() << "\n"; From 3504acc33e8b9ddd7de71d75cdc329a14dbf58d9 Mon Sep 17 00:00:00 2001 From: David Green Date: Thu, 16 Jul 2020 10:36:23 +0100 Subject: [PATCH 745/771] [ARM] Don't mark vctp as having sideeffects As far as I can tell, it should not be necessary for VCTP to be unpredictable in tail predicated loops. Either it has a a valid loop counter as a operand which will naturally keep it in the right loop, or it doesn't and it won't be converted to a tail predicated loop. Not marking it as having side effects allows it to be scheduled more cleanly for cases where it is not expected to become a tail predicate loop. Differential Revision: https://reviews.llvm.org/D83907 --- llvm/lib/Target/ARM/ARMInstrMVE.td | 1 - .../CodeGen/Thumb2/mve-float16regloops.ll | 34 +++++++++---------- llvm/test/CodeGen/Thumb2/mve-vctp.ll | 6 ++-- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td index 2a1f50d97e3b3..d6e725084d7f9 100644 --- a/llvm/lib/Target/ARM/ARMInstrMVE.td +++ b/llvm/lib/Target/ARM/ARMInstrMVE.td @@ -5605,7 +5605,6 @@ def MVE_VDWDUPu8 : MVE_VxWDUP<"vdwdup", "u8", 0b00, 0b1>; def MVE_VDWDUPu16 : MVE_VxWDUP<"vdwdup", "u16", 0b01, 0b1>; def MVE_VDWDUPu32 : MVE_VxWDUP<"vdwdup", "u32", 0b10, 0b1>; -let hasSideEffects = 1 in class MVE_VCTPInst size, list pattern=[]> : MVE_p<(outs VCCR:$P0), (ins rGPR:$Rn), NoItinerary, "vctp", suffix, "$Rn", vpred_n, "", pattern> { diff --git a/llvm/test/CodeGen/Thumb2/mve-float16regloops.ll b/llvm/test/CodeGen/Thumb2/mve-float16regloops.ll index 42e8cc91ede8e..e8ab7792b6dfc 100644 --- a/llvm/test/CodeGen/Thumb2/mve-float16regloops.ll +++ b/llvm/test/CodeGen/Thumb2/mve-float16regloops.ll @@ -796,23 +796,23 @@ define void @arm_fir_f32_1_4_mve(%struct.arm_fir_instance_f32* nocapture readonl ; CHECK-NEXT: .pad #16 ; CHECK-NEXT: sub sp, #16 ; CHECK-NEXT: ldrh r5, [r0] -; CHECK-NEXT: ldr.w r12, [r0, #4] +; CHECK-NEXT: ldr.w r9, [r0, #4] ; CHECK-NEXT: subs r6, r5, #1 ; CHECK-NEXT: cmp r6, #3 ; CHECK-NEXT: bhi .LBB15_6 ; CHECK-NEXT: @ %bb.1: @ %if.then ; CHECK-NEXT: ldr r7, [r0, #8] -; CHECK-NEXT: add.w r4, r12, r6, lsl #1 +; CHECK-NEXT: add.w r4, r9, r6, lsl #1 ; CHECK-NEXT: lsr.w lr, r3, #2 ; CHECK-NEXT: ldrh.w r8, [r7, #6] -; CHECK-NEXT: ldrh.w r9, [r7, #4] +; CHECK-NEXT: ldrh.w r12, [r7, #4] ; CHECK-NEXT: ldrh r6, [r7, #2] ; CHECK-NEXT: ldrh r7, [r7] ; CHECK-NEXT: wls lr, lr, .LBB15_5 ; CHECK-NEXT: @ %bb.2: @ %while.body.lr.ph ; CHECK-NEXT: str r5, [sp, #12] @ 4-byte Spill ; CHECK-NEXT: bic r5, r3, #3 -; CHECK-NEXT: add.w r10, r12, #2 +; CHECK-NEXT: add.w r10, r9, #2 ; CHECK-NEXT: str r5, [sp] @ 4-byte Spill ; CHECK-NEXT: add.w r5, r2, r5, lsl #1 ; CHECK-NEXT: str r5, [sp, #4] @ 4-byte Spill @@ -828,7 +828,7 @@ define void @arm_fir_f32_1_4_mve(%struct.arm_fir_instance_f32* nocapture readonl ; CHECK-NEXT: vmul.f16 q0, q0, r7 ; CHECK-NEXT: vfma.f16 q0, q1, r6 ; CHECK-NEXT: vldrw.u32 q1, [r5] -; CHECK-NEXT: vfma.f16 q0, q1, r9 +; CHECK-NEXT: vfma.f16 q0, q1, r12 ; CHECK-NEXT: vldrw.u32 q1, [r10, #4] ; CHECK-NEXT: add.w r10, r10, #8 ; CHECK-NEXT: vfma.f16 q0, q1, r8 @@ -838,7 +838,7 @@ define void @arm_fir_f32_1_4_mve(%struct.arm_fir_instance_f32* nocapture readonl ; CHECK-NEXT: ldr r2, [sp] @ 4-byte Reload ; CHECK-NEXT: ldr r1, [sp, #8] @ 4-byte Reload ; CHECK-NEXT: ldr r5, [sp, #12] @ 4-byte Reload -; CHECK-NEXT: add.w r12, r12, r2, lsl #1 +; CHECK-NEXT: add.w r9, r9, r2, lsl #1 ; CHECK-NEXT: add.w r1, r1, r2, lsl #1 ; CHECK-NEXT: ldr r2, [sp, #4] @ 4-byte Reload ; CHECK-NEXT: .LBB15_5: @ %while.end @@ -847,35 +847,35 @@ define void @arm_fir_f32_1_4_mve(%struct.arm_fir_instance_f32* nocapture readonl ; CHECK-NEXT: vctp.16 lr ; CHECK-NEXT: vpst ; CHECK-NEXT: vstrht.16 q0, [r4] -; CHECK-NEXT: vldrw.u32 q0, [r12] -; CHECK-NEXT: add.w r1, r12, #2 +; CHECK-NEXT: vldrw.u32 q0, [r9] +; CHECK-NEXT: add.w r1, r9, #2 ; CHECK-NEXT: vldrw.u32 q1, [r1] -; CHECK-NEXT: add.w r1, r12, #6 +; CHECK-NEXT: add.w r1, r9, #6 ; CHECK-NEXT: vmul.f16 q0, q0, r7 ; CHECK-NEXT: vfma.f16 q0, q1, r6 -; CHECK-NEXT: vldrw.u32 q1, [r12, #4] -; CHECK-NEXT: vfma.f16 q0, q1, r9 +; CHECK-NEXT: vldrw.u32 q1, [r9, #4] +; CHECK-NEXT: vfma.f16 q0, q1, r12 ; CHECK-NEXT: vldrw.u32 q1, [r1] ; CHECK-NEXT: vfma.f16 q0, q1, r8 ; CHECK-NEXT: vpst ; CHECK-NEXT: vstrht.16 q0, [r2] -; CHECK-NEXT: ldr.w r12, [r0, #4] +; CHECK-NEXT: ldr.w r9, [r0, #4] ; CHECK-NEXT: .LBB15_6: @ %if.end -; CHECK-NEXT: add.w r0, r12, r3, lsl #1 +; CHECK-NEXT: add.w r0, r9, r3, lsl #1 ; CHECK-NEXT: lsr.w lr, r5, #2 ; CHECK-NEXT: wls lr, lr, .LBB15_10 ; CHECK-NEXT: @ %bb.7: @ %while.body51.preheader ; CHECK-NEXT: bic r2, r5, #3 ; CHECK-NEXT: adds r1, r2, r3 -; CHECK-NEXT: mov r3, r12 -; CHECK-NEXT: add.w r1, r12, r1, lsl #1 +; CHECK-NEXT: mov r3, r9 +; CHECK-NEXT: add.w r1, r9, r1, lsl #1 ; CHECK-NEXT: .LBB15_8: @ %while.body51 ; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 ; CHECK-NEXT: vldrw.u32 q0, [r0], #8 ; CHECK-NEXT: vstrb.8 q0, [r3], #8 ; CHECK-NEXT: le lr, .LBB15_8 ; CHECK-NEXT: @ %bb.9: @ %while.end55.loopexit -; CHECK-NEXT: add.w r12, r12, r2, lsl #1 +; CHECK-NEXT: add.w r9, r9, r2, lsl #1 ; CHECK-NEXT: mov r0, r1 ; CHECK-NEXT: .LBB15_10: @ %while.end55 ; CHECK-NEXT: ands r1, r5, #3 @@ -884,7 +884,7 @@ define void @arm_fir_f32_1_4_mve(%struct.arm_fir_instance_f32* nocapture readonl ; CHECK-NEXT: vldrw.u32 q0, [r0] ; CHECK-NEXT: vctp.16 r1 ; CHECK-NEXT: vpst -; CHECK-NEXT: vstrht.16 q0, [r12] +; CHECK-NEXT: vstrht.16 q0, [r9] ; CHECK-NEXT: .LBB15_12: @ %if.end61 ; CHECK-NEXT: add sp, #16 ; CHECK-NEXT: pop.w {r4, r5, r6, r7, r8, r9, r10, r11, pc} diff --git a/llvm/test/CodeGen/Thumb2/mve-vctp.ll b/llvm/test/CodeGen/Thumb2/mve-vctp.ll index d6e4d492f5351..67bc161e02c64 100644 --- a/llvm/test/CodeGen/Thumb2/mve-vctp.ll +++ b/llvm/test/CodeGen/Thumb2/mve-vctp.ll @@ -4,8 +4,8 @@ define void @vctp8(i32 %arg, <16 x i8> *%in, <16 x i8>* %out) { ; CHECK-LABEL: vctp8: ; CHECK: @ %bb.0: -; CHECK-NEXT: vctp.8 r0 ; CHECK-NEXT: vldrw.u32 q1, [r1] +; CHECK-NEXT: vctp.8 r0 ; CHECK-NEXT: vmov.i32 q0, #0x0 ; CHECK-NEXT: vpsel q0, q1, q0 ; CHECK-NEXT: vstrw.32 q0, [r2] @@ -20,8 +20,8 @@ define void @vctp8(i32 %arg, <16 x i8> *%in, <16 x i8>* %out) { define void @vctp16(i32 %arg, <8 x i16> *%in, <8 x i16>* %out) { ; CHECK-LABEL: vctp16: ; CHECK: @ %bb.0: -; CHECK-NEXT: vctp.16 r0 ; CHECK-NEXT: vldrw.u32 q1, [r1] +; CHECK-NEXT: vctp.16 r0 ; CHECK-NEXT: vmov.i32 q0, #0x0 ; CHECK-NEXT: vpsel q0, q1, q0 ; CHECK-NEXT: vstrw.32 q0, [r2] @@ -36,8 +36,8 @@ define void @vctp16(i32 %arg, <8 x i16> *%in, <8 x i16>* %out) { define void @vctp32(i32 %arg, <4 x i32> *%in, <4 x i32>* %out) { ; CHECK-LABEL: vctp32: ; CHECK: @ %bb.0: -; CHECK-NEXT: vctp.32 r0 ; CHECK-NEXT: vldrw.u32 q1, [r1] +; CHECK-NEXT: vctp.32 r0 ; CHECK-NEXT: vmov.i32 q0, #0x0 ; CHECK-NEXT: vpsel q0, q1, q0 ; CHECK-NEXT: vstrw.32 q0, [r2] From d12ec0f752e7f2c7f7252539da2d124264ec33f7 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 18 Jul 2020 22:22:41 +0200 Subject: [PATCH 746/771] [InstCombine] Fix store merge worklist management (PR46680) Fixes https://bugs.llvm.org/show_bug.cgi?id=46680. Just like insertions through IRBuilder, InsertNewInstBefore() should be using the deferred worklist mechanism, so that processing of newly added instructions is prioritized. There's one side-effect of the worklist order change which could be classified as a regression. An add op gets pushed through a select that at the time is not a umax. We could add a reverse transform that tries to push adds in the reverse direction to restore a min/max, but that seems like a sure way of getting infinite loops... Seems like something that should best wait on min/max intrinsics. Differential Revision: https://reviews.llvm.org/D84109 --- .../InstCombine/InstCombineInternal.h | 2 +- .../Transforms/InstCombine/minmax-fold.ll | 20 +++++++++---------- llvm/test/Transforms/InstCombine/pr46680.ll | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h index f918dc7198ca9..ca51f37af4d93 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -653,7 +653,7 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner "New instruction already inserted into a basic block!"); BasicBlock *BB = Old.getParent(); BB->getInstList().insert(Old.getIterator(), New); // Insert inst - Worklist.push(New); + Worklist.add(New); return New; } diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll index 5ee38978ed782..dcf060c09613e 100644 --- a/llvm/test/Transforms/InstCombine/minmax-fold.ll +++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll @@ -953,8 +953,8 @@ define i32 @add_umin(i32 %x) { define i32 @add_umin_constant_limit(i32 %x) { ; CHECK-LABEL: @add_umin_constant_limit( -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[X:%.*]], 0 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 41, i32 42 +; CHECK-NEXT: [[DOTNOT:%.*]] = icmp eq i32 [[X:%.*]], 0 +; CHECK-NEXT: [[R:%.*]] = select i1 [[DOTNOT]], i32 41, i32 42 ; CHECK-NEXT: ret i32 [[R]] ; %a = add nuw i32 %x, 41 @@ -1165,8 +1165,8 @@ define <2 x i33> @add_umax_vec(<2 x i33> %x) { define i8 @PR14613_umin(i8 %x) { ; CHECK-LABEL: @PR14613_umin( -; CHECK-NEXT: [[U7:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 15) -; CHECK-NEXT: ret i8 [[U7]] +; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[X:%.*]], i8 15) +; CHECK-NEXT: ret i8 [[TMP1]] ; %u4 = zext i8 %x to i32 %u5 = add nuw nsw i32 %u4, 15 @@ -1179,8 +1179,8 @@ define i8 @PR14613_umin(i8 %x) { define i8 @PR14613_umax(i8 %x) { ; CHECK-LABEL: @PR14613_umax( ; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], -16 -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 -16 -; CHECK-NEXT: [[U7:%.*]] = add nsw i8 [[TMP2]], 15 +; CHECK-NEXT: [[X_OP:%.*]] = add i8 [[X]], 15 +; CHECK-NEXT: [[U7:%.*]] = select i1 [[TMP1]], i8 [[X_OP]], i8 -1 ; CHECK-NEXT: ret i8 [[U7]] ; %u4 = zext i8 %x to i32 @@ -1422,8 +1422,8 @@ define <2 x i33> @add_smax_vec(<2 x i33> %x) { define i8 @PR14613_smin(i8 %x) { ; CHECK-LABEL: @PR14613_smin( ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 40 -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 40 -; CHECK-NEXT: [[U7:%.*]] = add nsw i8 [[TMP2]], 15 +; CHECK-NEXT: [[X_OP:%.*]] = add i8 [[X]], 15 +; CHECK-NEXT: [[U7:%.*]] = select i1 [[TMP1]], i8 [[X_OP]], i8 55 ; CHECK-NEXT: ret i8 [[U7]] ; %u4 = sext i8 %x to i32 @@ -1437,8 +1437,8 @@ define i8 @PR14613_smin(i8 %x) { define i8 @PR14613_smax(i8 %x) { ; CHECK-LABEL: @PR14613_smax( ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X:%.*]], 40 -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[TMP1]], i8 [[X]], i8 40 -; CHECK-NEXT: [[U7:%.*]] = add nuw i8 [[TMP2]], 15 +; CHECK-NEXT: [[X_OP:%.*]] = add i8 [[X]], 15 +; CHECK-NEXT: [[U7:%.*]] = select i1 [[TMP1]], i8 [[X_OP]], i8 55 ; CHECK-NEXT: ret i8 [[U7]] ; %u4 = sext i8 %x to i32 diff --git a/llvm/test/Transforms/InstCombine/pr46680.ll b/llvm/test/Transforms/InstCombine/pr46680.ll index 90ea2e110afe4..59d449d5dc23a 100644 --- a/llvm/test/Transforms/InstCombine/pr46680.ll +++ b/llvm/test/Transforms/InstCombine/pr46680.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -S -instcombine -instcombine-infinite-loop-threshold=3 < %s | FileCheck %s +; RUN: opt -S -instcombine -instcombine-infinite-loop-threshold=2 < %s | FileCheck %s target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu" From 7393d7574c0911b2fd88dd10d093af3efe4dd0cf Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 19 Jul 2020 09:24:03 -0400 Subject: [PATCH 747/771] [InstSimplify] fold fcmp with infinity constant using isKnownNeverInfinity This is a step towards trying to remove unnecessary FP compares with infinity when compiling with -ffinite-math-only or similar. I'm intentionally not checking FMF on the fcmp itself because I'm assuming that will go away eventually. The analysis part of this was added with rGcd481136 for use with isKnownNeverNaN. Similarly, that could be an enhancement here to get predicates like 'one' and 'ueq'. Differential Revision: https://reviews.llvm.org/D84035 --- llvm/lib/Analysis/InstructionSimplify.cpp | 7 +++++++ .../InstSimplify/floating-point-compare.ll | 21 +++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index d3bdf9d6aafd0..8fbcee84a1567 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3703,6 +3703,13 @@ static Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, break; } } + + // LHS == Inf + if (Pred == FCmpInst::FCMP_OEQ && isKnownNeverInfinity(LHS, Q.TLI)) + return getFalse(RetTy); + // LHS != Inf + if (Pred == FCmpInst::FCMP_UNE && isKnownNeverInfinity(LHS, Q.TLI)) + return getTrue(RetTy); } if (C->isNegative() && !C->isNegZero()) { assert(!C->isNaN() && "Unexpected NaN constant!"); diff --git a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll index 4f7334762f536..718a4427e15e3 100644 --- a/llvm/test/Transforms/InstSimplify/floating-point-compare.ll +++ b/llvm/test/Transforms/InstSimplify/floating-point-compare.ll @@ -1041,9 +1041,7 @@ define <2 x i1> @unorderedCompareWithNaNVector_undef_elt(<2 x double> %A) { define i1 @is_infinite(float %x) { ; CHECK-LABEL: @is_infinite( -; CHECK-NEXT: [[XABS:%.*]] = call ninf float @llvm.fabs.f32(float [[X:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fcmp oeq float [[XABS]], 0x7FF0000000000000 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %xabs = call ninf float @llvm.fabs.f32(float %x) %r = fcmp oeq float %xabs, 0x7FF0000000000000 @@ -1052,15 +1050,15 @@ define i1 @is_infinite(float %x) { define <2 x i1> @is_infinite_neg(<2 x float> %x) { ; CHECK-LABEL: @is_infinite_neg( -; CHECK-NEXT: [[X42:%.*]] = fadd ninf <2 x float> [[X:%.*]], -; CHECK-NEXT: [[R:%.*]] = fcmp oeq <2 x float> [[X42]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %x42 = fadd ninf <2 x float> %x, %r = fcmp oeq <2 x float> %x42, ret <2 x i1> %r } +; Negative test - but this could be reduced to 'uno' outside of instsimplify. + define i1 @is_infinite_or_nan(float %x) { ; CHECK-LABEL: @is_infinite_or_nan( ; CHECK-NEXT: [[X42:%.*]] = fadd ninf float [[X:%.*]], 4.200000e+01 @@ -1074,10 +1072,7 @@ define i1 @is_infinite_or_nan(float %x) { define i1 @is_finite_or_nan(i1 %c, double %x) { ; CHECK-LABEL: @is_finite_or_nan( -; CHECK-NEXT: [[XX:%.*]] = fmul ninf double [[X:%.*]], [[X]] -; CHECK-NEXT: [[S:%.*]] = select i1 [[C:%.*]], double 4.200000e+01, double [[XX]] -; CHECK-NEXT: [[R:%.*]] = fcmp une double [[S]], 0x7FF0000000000000 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %xx = fmul ninf double %x, %x %s = select i1 %c, double 42.0, double %xx @@ -1087,15 +1082,15 @@ define i1 @is_finite_or_nan(i1 %c, double %x) { define <2 x i1> @is_finite_or_nan_commute(<2 x i8> %x) { ; CHECK-LABEL: @is_finite_or_nan_commute( -; CHECK-NEXT: [[CAST:%.*]] = uitofp <2 x i8> [[X:%.*]] to <2 x float> -; CHECK-NEXT: [[R:%.*]] = fcmp une <2 x float> , [[CAST]] -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> ; %cast = uitofp <2 x i8> %x to <2 x float> %r = fcmp une <2 x float> , %cast ret <2 x i1> %r } +; Negative test - but this could be reduced to 'ord' outside of instsimplify. + define i1 @is_finite_and_ordered(double %x) { ; CHECK-LABEL: @is_finite_and_ordered( ; CHECK-NEXT: [[XX:%.*]] = fmul ninf double [[X:%.*]], [[X]] From fb5577d4f883ba21a6fe048ffd59ca3659cdb491 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sun, 19 Jul 2020 16:09:46 +0300 Subject: [PATCH 748/771] [NFCI][GVN] Make IsValueFullyAvailableInBlock() readable - use enum class instead of magic numbers This does not change any logic, it only wraps the magic 0/1/2/3 constants into an enum class. --- llvm/lib/Transforms/Scalar/GVN.cpp | 65 +++++++++++++++++++----------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp index b16f8591b5a46..0b416cc4afb86 100644 --- a/llvm/lib/Transforms/Scalar/GVN.cpp +++ b/llvm/lib/Transforms/Scalar/GVN.cpp @@ -667,6 +667,19 @@ LLVM_DUMP_METHOD void GVN::dump(DenseMap& d) const { } #endif +enum class AvaliabilityState : char { + /// We know the block *is not* fully available. This is a fixpoint. + Unavaliable = 0, + /// We know the block *is* fully available. This is a fixpoint. + Avaliable = 1, + /// We do not know whether the block is fully available or not, + /// but we are currently speculating that it will be. + SpeculativelyAvaliable = 2, + /// We are speculating for this block and have used that + /// to speculate for other blocks. + SpeculativelyAvaliableAndUsedForSpeculation = 3, +}; + /// Return true if we can prove that the value /// we're analyzing is fully available in the specified block. As we go, keep /// track of which blocks we know are fully alive in FullyAvailableBlocks. This @@ -677,24 +690,27 @@ LLVM_DUMP_METHOD void GVN::dump(DenseMap& d) const { /// currently speculating that it will be. /// 3) we are speculating for this block and have used that to speculate for /// other blocks. -static bool IsValueFullyAvailableInBlock(BasicBlock *BB, - DenseMap &FullyAvailableBlocks, - uint32_t RecurseDepth) { +static bool IsValueFullyAvailableInBlock( + BasicBlock *BB, + DenseMap &FullyAvailableBlocks, + uint32_t RecurseDepth) { if (RecurseDepth > MaxRecurseDepth) return false; - // Optimistically assume that the block is fully available and check to see - // if we already know about this block in one lookup. - std::pair::iterator, bool> IV = - FullyAvailableBlocks.insert(std::make_pair(BB, 2)); + // Optimistically assume that the block is speculatively available and check + // to see if we already know about this block in one lookup. + std::pair::iterator, bool> IV = + FullyAvailableBlocks.insert( + std::make_pair(BB, AvaliabilityState::SpeculativelyAvaliable)); // If the entry already existed for this block, return the precomputed value. if (!IV.second) { // If this is a speculative "available" value, mark it as being used for // speculation of other blocks. - if (IV.first->second == 2) - IV.first->second = 3; - return IV.first->second != 0; + if (IV.first->second == AvaliabilityState::SpeculativelyAvaliable) + IV.first->second = + AvaliabilityState::SpeculativelyAvaliableAndUsedForSpeculation; + return IV.first->second != AvaliabilityState::Unavaliable; } // Otherwise, see if it is fully available in all predecessors. @@ -717,29 +733,30 @@ static bool IsValueFullyAvailableInBlock(BasicBlock *BB, // all, a fully-available block. We have a problem if we speculated on this and // used the speculation to mark other blocks as available. SpeculationFailure: - char &BBVal = FullyAvailableBlocks[BB]; + AvaliabilityState &BBVal = FullyAvailableBlocks[BB]; - // If we didn't speculate on this, just return with it set to false. - if (BBVal == 2) { - BBVal = 0; + // If we didn't speculate on this, just return with it set to unavaliable. + if (BBVal == AvaliabilityState::SpeculativelyAvaliable) { + BBVal = AvaliabilityState::Unavaliable; return false; } - // If we did speculate on this value, we could have blocks set to 1 that are - // incorrect. Walk the (transitive) successors of this block and mark them as - // 0 if set to one. + // If we did speculate on this value, we could have blocks set to + // speculatively avaliable that are incorrect. Walk the (transitive) + // successors of this block and mark them as unavaliable instead. SmallVector BBWorklist; BBWorklist.push_back(BB); do { BasicBlock *Entry = BBWorklist.pop_back_val(); - // Note that this sets blocks to 0 (unavailable) if they happen to not + // Note that this sets blocks to unavailable if they happen to not // already be in FullyAvailableBlocks. This is safe. - char &EntryVal = FullyAvailableBlocks[Entry]; - if (EntryVal == 0) continue; // Already unavailable. + AvaliabilityState &EntryVal = FullyAvailableBlocks[Entry]; + if (EntryVal == AvaliabilityState::Unavaliable) + continue; // Already unavailable. // Mark as unavailable. - EntryVal = 0; + EntryVal = AvaliabilityState::Unavaliable; BBWorklist.append(succ_begin(Entry), succ_end(Entry)); } while (!BBWorklist.empty()); @@ -1107,11 +1124,11 @@ bool GVN::PerformLoadPRE(LoadInst *LI, AvailValInBlkVect &ValuesPerBlock, // Check to see how many predecessors have the loaded value fully // available. MapVector PredLoads; - DenseMap FullyAvailableBlocks; + DenseMap FullyAvailableBlocks; for (const AvailableValueInBlock &AV : ValuesPerBlock) - FullyAvailableBlocks[AV.BB] = true; + FullyAvailableBlocks[AV.BB] = AvaliabilityState::Avaliable; for (BasicBlock *UnavailableBB : UnavailableBlocks) - FullyAvailableBlocks[UnavailableBB] = false; + FullyAvailableBlocks[UnavailableBB] = AvaliabilityState::Unavaliable; SmallVector CriticalEdgePred; for (BasicBlock *Pred : predecessors(LoadBB)) { From c6e13667e787b3a72b794422ab506d5403ddcd21 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 9 Jul 2020 22:52:50 +0200 Subject: [PATCH 749/771] [PredicateInfo] Add a method to interpret predicate as cmp constraint Both users of predicteinfo (NewGVN and SCCP) are interested in getting a cmp constraint on the predicated value. They currently implement separate logic for this. This patch adds a common method for this in PredicateBase. This enables a missing bit of PredicateInfo handling in SCCP: Now the predicate on the condition itself is also used. For switches it means we know that the switched-on value is the same as the case value. For assumes/branches we know that the condition is true or false. Differential Revision: https://reviews.llvm.org/D83640 --- .../llvm/Transforms/Utils/PredicateInfo.h | 10 ++ llvm/lib/Transforms/Scalar/NewGVN.cpp | 97 +++++-------------- llvm/lib/Transforms/Scalar/SCCP.cpp | 53 ++-------- llvm/lib/Transforms/Utils/PredicateInfo.cpp | 47 +++++++++ .../Transforms/SCCP/predicateinfo-cond.ll | 23 ++--- 5 files changed, 99 insertions(+), 131 deletions(-) diff --git a/llvm/include/llvm/Transforms/Utils/PredicateInfo.h b/llvm/include/llvm/Transforms/Utils/PredicateInfo.h index cdac4142555db..c922476ac79da 100644 --- a/llvm/include/llvm/Transforms/Utils/PredicateInfo.h +++ b/llvm/include/llvm/Transforms/Utils/PredicateInfo.h @@ -70,6 +70,13 @@ class raw_ostream; enum PredicateType { PT_Branch, PT_Assume, PT_Switch }; +/// Constraint for a predicate of the form "cmp Pred Op, OtherOp", where Op +/// is the value the constraint applies to (the ssa.copy result). +struct PredicateConstraint { + CmpInst::Predicate Predicate; + Value *OtherOp; +}; + // Base class for all predicate information we provide. // All of our predicate information has at least a comparison. class PredicateBase : public ilist_node { @@ -95,6 +102,9 @@ class PredicateBase : public ilist_node { PB->Type == PT_Switch; } + /// Fetch condition in the form of PredicateConstraint, if possible. + Optional getConstraint() const; + protected: PredicateBase(PredicateType PT, Value *Op, Value *Condition) : Type(PT), OriginalOp(Op), Condition(Condition) {} diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index 45d01cc1b5845..cfadfbb585b9f 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -1539,86 +1539,39 @@ NewGVN::performSymbolicPredicateInfoEvaluation(Instruction *I) const { LLVM_DEBUG(dbgs() << "Found predicate info from instruction !\n"); - auto *CopyOf = I->getOperand(0); - auto *Cond = PI->Condition; - - // If this a copy of the condition, it must be either true or false depending - // on the predicate info type and edge. - if (CopyOf == Cond) { - // We should not need to add predicate users because the predicate info is - // already a use of this operand. - if (isa(PI)) - return createConstantExpression(ConstantInt::getTrue(Cond->getType())); - if (auto *PBranch = dyn_cast(PI)) { - if (PBranch->TrueEdge) - return createConstantExpression(ConstantInt::getTrue(Cond->getType())); - return createConstantExpression(ConstantInt::getFalse(Cond->getType())); - } - if (auto *PSwitch = dyn_cast(PI)) - return createConstantExpression(cast(PSwitch->CaseValue)); - } - - // Not a copy of the condition, so see what the predicates tell us about this - // value. First, though, we check to make sure the value is actually a copy - // of one of the condition operands. It's possible, in certain cases, for it - // to be a copy of a predicateinfo copy. In particular, if two branch - // operations use the same condition, and one branch dominates the other, we - // will end up with a copy of a copy. This is currently a small deficiency in - // predicateinfo. What will end up happening here is that we will value - // number both copies the same anyway. - - // Everything below relies on the condition being a comparison. - auto *Cmp = dyn_cast(Cond); - if (!Cmp) + const Optional &Constraint = PI->getConstraint(); + if (!Constraint) return nullptr; - if (CopyOf != Cmp->getOperand(0) && CopyOf != Cmp->getOperand(1)) { - LLVM_DEBUG(dbgs() << "Copy is not of any condition operands!\n"); - return nullptr; - } - Value *FirstOp = lookupOperandLeader(Cmp->getOperand(0)); - Value *SecondOp = lookupOperandLeader(Cmp->getOperand(1)); - bool SwappedOps = false; + CmpInst::Predicate Predicate = Constraint->Predicate; + Value *CmpOp0 = I->getOperand(0); + Value *CmpOp1 = Constraint->OtherOp; + + Value *FirstOp = lookupOperandLeader(CmpOp0); + Value *SecondOp = lookupOperandLeader(CmpOp1); + Value *AdditionallyUsedValue = CmpOp0; + // Sort the ops. if (shouldSwapOperands(FirstOp, SecondOp)) { std::swap(FirstOp, SecondOp); - SwappedOps = true; + Predicate = CmpInst::getSwappedPredicate(Predicate); + AdditionallyUsedValue = CmpOp1; } - CmpInst::Predicate Predicate = - SwappedOps ? Cmp->getSwappedPredicate() : Cmp->getPredicate(); - - if (isa(PI)) { - // If we assume the operands are equal, then they are equal. - if (Predicate == CmpInst::ICMP_EQ) { - addPredicateUsers(PI, I); - addAdditionalUsers(SwappedOps ? Cmp->getOperand(1) : Cmp->getOperand(0), - I); - return createVariableOrConstant(FirstOp); - } + + if (Predicate == CmpInst::ICMP_EQ) { + addPredicateUsers(PI, I); + addAdditionalUsers(AdditionallyUsedValue, I); + return createVariableOrConstant(FirstOp); } - if (const auto *PBranch = dyn_cast(PI)) { - // If we are *not* a copy of the comparison, we may equal to the other - // operand when the predicate implies something about equality of - // operations. In particular, if the comparison is true/false when the - // operands are equal, and we are on the right edge, we know this operation - // is equal to something. - if ((PBranch->TrueEdge && Predicate == CmpInst::ICMP_EQ) || - (!PBranch->TrueEdge && Predicate == CmpInst::ICMP_NE)) { - addPredicateUsers(PI, I); - addAdditionalUsers(SwappedOps ? Cmp->getOperand(1) : Cmp->getOperand(0), - I); - return createVariableOrConstant(FirstOp); - } - // Handle the special case of floating point. - if (((PBranch->TrueEdge && Predicate == CmpInst::FCMP_OEQ) || - (!PBranch->TrueEdge && Predicate == CmpInst::FCMP_UNE)) && - isa(FirstOp) && !cast(FirstOp)->isZero()) { - addPredicateUsers(PI, I); - addAdditionalUsers(SwappedOps ? Cmp->getOperand(1) : Cmp->getOperand(0), - I); - return createConstantExpression(cast(FirstOp)); - } + + // Handle the special case of floating point. + if (Predicate == CmpInst::FCMP_OEQ && isa(FirstOp) && + !cast(FirstOp)->isZero()) { + addPredicateUsers(PI, I); + addAdditionalUsers(AdditionallyUsedValue, I); + return createConstantExpression(cast(FirstOp)); } + return nullptr; } diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index 2a5fcfc092685..11ac7d7e15847 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -1262,55 +1262,22 @@ void SCCPSolver::handleCallResult(CallBase &CB) { auto *PI = getPredicateInfoFor(&CB); assert(PI && "Missing predicate info for ssa.copy"); - CmpInst *Cmp; - bool TrueEdge; - if (auto *PBranch = dyn_cast(PI)) { - Cmp = dyn_cast(PBranch->Condition); - TrueEdge = PBranch->TrueEdge; - } else if (auto *PAssume = dyn_cast(PI)) { - Cmp = dyn_cast(PAssume->Condition); - TrueEdge = true; - } else { + const Optional &Constraint = PI->getConstraint(); + if (!Constraint) { mergeInValue(ValueState[&CB], &CB, CopyOfVal); return; } - // Everything below relies on the condition being a comparison. - if (!Cmp) { - mergeInValue(ValueState[&CB], &CB, CopyOfVal); - return; - } + CmpInst::Predicate Pred = Constraint->Predicate; + Value *OtherOp = Constraint->OtherOp; - Value *RenamedOp = PI->RenamedOp; - Value *CmpOp0 = Cmp->getOperand(0); - Value *CmpOp1 = Cmp->getOperand(1); - // Bail out if neither of the operands matches RenamedOp. - if (CmpOp0 != RenamedOp && CmpOp1 != RenamedOp) { - mergeInValue(ValueState[&CB], &CB, getValueState(CopyOf)); + // Wait until OtherOp is resolved. + if (getValueState(OtherOp).isUnknown()) { + addAdditionalUser(OtherOp, &CB); return; } - auto Pred = Cmp->getPredicate(); - if (CmpOp1 == RenamedOp) { - std::swap(CmpOp0, CmpOp1); - Pred = Cmp->getSwappedPredicate(); - } - - // Wait until CmpOp1 is resolved. - if (getValueState(CmpOp1).isUnknown()) { - addAdditionalUser(CmpOp1, &CB); - return; - } - - // The code below relies on PredicateInfo only inserting copies for the - // true branch when the branch condition is an AND and only inserting - // copies for the false branch when the branch condition is an OR. This - // ensures we can intersect the range from the condition with the range of - // CopyOf. - if (!TrueEdge) - Pred = CmpInst::getInversePredicate(Pred); - - ValueLatticeElement CondVal = getValueState(CmpOp1); + ValueLatticeElement CondVal = getValueState(OtherOp); ValueLatticeElement &IV = ValueState[&CB]; if (CondVal.isConstantRange() || CopyOfVal.isConstantRange()) { auto ImposedCR = @@ -1334,7 +1301,7 @@ void SCCPSolver::handleCallResult(CallBase &CB) { if (!CopyOfCR.contains(NewCR) && CopyOfCR.getSingleMissingElement()) NewCR = CopyOfCR; - addAdditionalUser(CmpOp1, &CB); + addAdditionalUser(OtherOp, &CB); // TODO: Actually filp MayIncludeUndef for the created range to false, // once most places in the optimizer respect the branches on // undef/poison are UB rule. The reason why the new range cannot be @@ -1351,7 +1318,7 @@ void SCCPSolver::handleCallResult(CallBase &CB) { } else if (Pred == CmpInst::ICMP_EQ && CondVal.isConstant()) { // For non-integer values or integer constant expressions, only // propagate equal constants. - addAdditionalUser(CmpOp1, &CB); + addAdditionalUser(OtherOp, &CB); mergeInValue(IV, &CB, CondVal); return; } diff --git a/llvm/lib/Transforms/Utils/PredicateInfo.cpp b/llvm/lib/Transforms/Utils/PredicateInfo.cpp index 99b64a7462f62..280d3a996d508 100644 --- a/llvm/lib/Transforms/Utils/PredicateInfo.cpp +++ b/llvm/lib/Transforms/Utils/PredicateInfo.cpp @@ -822,6 +822,53 @@ PredicateInfo::~PredicateInfo() { } } +Optional PredicateBase::getConstraint() const { + switch (Type) { + case PT_Assume: + case PT_Branch: { + bool TrueEdge = true; + if (auto *PBranch = dyn_cast(this)) + TrueEdge = PBranch->TrueEdge; + + if (Condition == RenamedOp) { + return {{CmpInst::ICMP_EQ, + TrueEdge ? ConstantInt::getTrue(Condition->getType()) + : ConstantInt::getFalse(Condition->getType())}}; + } + + CmpInst *Cmp = dyn_cast(Condition); + assert(Cmp && "Condition should be a CmpInst"); + + CmpInst::Predicate Pred; + Value *OtherOp; + if (Cmp->getOperand(0) == RenamedOp) { + Pred = Cmp->getPredicate(); + OtherOp = Cmp->getOperand(1); + } else if (Cmp->getOperand(1) == RenamedOp) { + Pred = Cmp->getSwappedPredicate(); + OtherOp = Cmp->getOperand(0); + } else { + // TODO: Make this an assertion once RenamedOp is fully accurate. + return None; + } + + // Invert predicate along false edge. + if (!TrueEdge) + Pred = CmpInst::getInversePredicate(Pred); + + return {{Pred, OtherOp}}; + } + case PT_Switch: + if (Condition != RenamedOp) { + // TODO: Make this an assertion once RenamedOp is fully accurate. + return None; + } + + return {{CmpInst::ICMP_EQ, cast(this)->CaseValue}}; + } + llvm_unreachable("Unknown predicate type"); +} + void PredicateInfo::verifyPredicateInfo() const {} char PredicateInfoPrinterLegacyPass::ID = 0; diff --git a/llvm/test/Transforms/SCCP/predicateinfo-cond.ll b/llvm/test/Transforms/SCCP/predicateinfo-cond.ll index d8528918babed..d98b3cc76d928 100644 --- a/llvm/test/Transforms/SCCP/predicateinfo-cond.ll +++ b/llvm/test/Transforms/SCCP/predicateinfo-cond.ll @@ -11,16 +11,13 @@ define i32 @switch(i32 %x) { ; CHECK-NEXT: i32 2, label [[CASE_2:%.*]] ; CHECK-NEXT: ] ; CHECK: case.0: -; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 1 ; CHECK-NEXT: br label [[END:%.*]] ; CHECK: case.2: -; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], 1 ; CHECK-NEXT: br label [[END]] ; CHECK: case.default: ; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[ADD]], [[CASE_0]] ], [ [[SUB]], [[CASE_2]] ], [ 1, [[CASE_DEFAULT]] ] -; CHECK-NEXT: ret i32 [[PHI]] +; CHECK-NEXT: ret i32 1 ; switch i32 %x, label %case.default [ i32 0, label %case.0 @@ -47,7 +44,7 @@ define i1 @assume(i32 %x) { ; CHECK-LABEL: @assume( ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sge i32 %x, 0 call void @llvm.assume(i1 %cmp) @@ -59,23 +56,17 @@ define i32 @branch(i32 %x) { ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN1:%.*]], label [[IF_THEN2:%.*]] ; CHECK: if.then1: -; CHECK-NEXT: br i1 [[CMP]], label [[IF2_THEN1:%.*]], label [[IF2_THEN2:%.*]] +; CHECK-NEXT: br label [[IF2_THEN1:%.*]] ; CHECK: if2.then1: ; CHECK-NEXT: br label [[IF2_END:%.*]] -; CHECK: if2.then2: -; CHECK-NEXT: br label [[IF2_END]] ; CHECK: if2.end: -; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ 0, [[IF2_THEN1]] ], [ 1, [[IF2_THEN2]] ] -; CHECK-NEXT: ret i32 [[PHI]] +; CHECK-NEXT: ret i32 0 ; CHECK: if.then2: -; CHECK-NEXT: br i1 [[CMP]], label [[IF3_THEN1:%.*]], label [[IF3_THEN2:%.*]] -; CHECK: if3.then1: -; CHECK-NEXT: br label [[IF3_END:%.*]] +; CHECK-NEXT: br label [[IF3_THEN2:%.*]] ; CHECK: if3.then2: -; CHECK-NEXT: br label [[IF3_END]] +; CHECK-NEXT: br label [[IF3_END:%.*]] ; CHECK: if3.end: -; CHECK-NEXT: [[PHI2:%.*]] = phi i32 [ 0, [[IF3_THEN1]] ], [ 1, [[IF3_THEN2]] ] -; CHECK-NEXT: ret i32 [[PHI2]] +; CHECK-NEXT: ret i32 1 ; %cmp = icmp sge i32 %x, 0 br i1 %cmp, label %if.then1, label %if.then2 From 2f3862eb9f21e8a0d48505637fefe6e5e295c18c Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sun, 19 Jul 2020 16:37:03 +0300 Subject: [PATCH 750/771] Reland "[InstCombine] Lower infinite combine loop detection thresholds" This reverts commit 4500db8c59621a31c622862a2946457fdee481ce, which was reverted because lower thresholds exposed a new issue (PR46680). Now that it was resolved by d12ec0f752e7f2c7f7252539da2d124264ec33f7, we can reinstate lower limits and wait for a new bugreport before reverting this again... --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index b3254c10a0b2b..8eac8637cb9e7 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -123,8 +123,13 @@ STATISTIC(NumReassoc , "Number of reassociations"); DEBUG_COUNTER(VisitCounter, "instcombine-visit", "Controls which instructions are visited"); +// FIXME: these limits eventually should be as low as 2. static constexpr unsigned InstCombineDefaultMaxIterations = 1000; +#ifndef NDEBUG +static constexpr unsigned InstCombineDefaultInfiniteLoopThreshold = 100; +#else static constexpr unsigned InstCombineDefaultInfiniteLoopThreshold = 1000; +#endif static cl::opt EnableCodeSinking("instcombine-code-sinking", cl::desc("Enable code sinking"), From 50afa18772daca0b6de253a7c5311c81b0a46682 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 19 Jul 2020 10:03:55 -0400 Subject: [PATCH 751/771] [x86] split FMA with fast-math-flags to avoid libcall fma reassoc A, B, C --> fadd (fmul A, B), C (when target has no FMA hardware) C/C++ code may use explicit fma() calls (which become LLVM fma intrinsics in IR) but then gets compiled with -ffast-math or similar. For targets that do not have FMA hardware, we don't want to go out to the math library for a precise but slow FMA result. I tried this as a generic DAGCombine, but it caused infinite looping on more than 1 other target, so there's likely some over-reaching fma formation happening. There's also a potential intersection of strict FP with fast-math here. Deferring to current behavior for that case (assuming that strict-ness overrides fast-ness). Differential Revision: https://reviews.llvm.org/D83981 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 17 +++-- llvm/test/CodeGen/X86/fma.ll | 92 ++++++------------------- 2 files changed, 33 insertions(+), 76 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index ea4b4734225d4..bb32a17bcc122 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -46131,14 +46131,23 @@ static SDValue combineFMA(SDNode *N, SelectionDAG &DAG, if (!TLI.isTypeLegal(VT)) return SDValue(); - EVT ScalarVT = VT.getScalarType(); - if ((ScalarVT != MVT::f32 && ScalarVT != MVT::f64) || !Subtarget.hasAnyFMA()) - return SDValue(); - SDValue A = N->getOperand(IsStrict ? 1 : 0); SDValue B = N->getOperand(IsStrict ? 2 : 1); SDValue C = N->getOperand(IsStrict ? 3 : 2); + // If the operation allows fast-math and the target does not support FMA, + // split this into mul+add to avoid libcall(s). + SDNodeFlags Flags = N->getFlags(); + if (!IsStrict && Flags.hasAllowReassociation() && + TLI.isOperationExpand(ISD::FMA, VT)) { + SDValue Fmul = DAG.getNode(ISD::FMUL, dl, VT, A, B, Flags); + return DAG.getNode(ISD::FADD, dl, VT, Fmul, C, Flags); + } + + EVT ScalarVT = VT.getScalarType(); + if ((ScalarVT != MVT::f32 && ScalarVT != MVT::f64) || !Subtarget.hasAnyFMA()) + return SDValue(); + auto invertIfNegative = [&DAG, &TLI, &DCI](SDValue &V) { bool CodeSize = DAG.getMachineFunction().getFunction().hasOptSize(); bool LegalOperations = !DCI.isBeforeLegalizeOps(); diff --git a/llvm/test/CodeGen/X86/fma.ll b/llvm/test/CodeGen/X86/fma.ll index 01b80c2dfdec1..91ba1c8891409 100644 --- a/llvm/test/CodeGen/X86/fma.ll +++ b/llvm/test/CodeGen/X86/fma.ll @@ -73,9 +73,15 @@ define float @test_f32_reassoc(float %a, float %b, float %c) #0 { ; ; FMACALL32-LABEL: test_f32_reassoc: ; FMACALL32: ## %bb.0: -; FMACALL32-NEXT: jmp _fmaf ## TAILCALL -; FMACALL32-NEXT: ## encoding: [0xeb,A] -; FMACALL32-NEXT: ## fixup A - offset: 1, value: _fmaf-1, kind: FK_PCRel_1 +; FMACALL32-NEXT: pushl %eax ## encoding: [0x50] +; FMACALL32-NEXT: vmovss {{[0-9]+}}(%esp), %xmm0 ## encoding: [0xc5,0xfa,0x10,0x44,0x24,0x08] +; FMACALL32-NEXT: ## xmm0 = mem[0],zero,zero,zero +; FMACALL32-NEXT: vmulss {{[0-9]+}}(%esp), %xmm0, %xmm0 ## encoding: [0xc5,0xfa,0x59,0x44,0x24,0x0c] +; FMACALL32-NEXT: vaddss {{[0-9]+}}(%esp), %xmm0, %xmm0 ## encoding: [0xc5,0xfa,0x58,0x44,0x24,0x10] +; FMACALL32-NEXT: vmovss %xmm0, (%esp) ## encoding: [0xc5,0xfa,0x11,0x04,0x24] +; FMACALL32-NEXT: flds (%esp) ## encoding: [0xd9,0x04,0x24] +; FMACALL32-NEXT: popl %eax ## encoding: [0x58] +; FMACALL32-NEXT: retl ## encoding: [0xc3] ; ; FMA64-LABEL: test_f32_reassoc: ; FMA64: ## %bb.0: @@ -85,9 +91,9 @@ define float @test_f32_reassoc(float %a, float %b, float %c) #0 { ; ; FMACALL64-LABEL: test_f32_reassoc: ; FMACALL64: ## %bb.0: -; FMACALL64-NEXT: jmp _fmaf ## TAILCALL -; FMACALL64-NEXT: ## encoding: [0xeb,A] -; FMACALL64-NEXT: ## fixup A - offset: 1, value: _fmaf-1, kind: FK_PCRel_1 +; FMACALL64-NEXT: mulss %xmm1, %xmm0 ## encoding: [0xf3,0x0f,0x59,0xc1] +; FMACALL64-NEXT: addss %xmm2, %xmm0 ## encoding: [0xf3,0x0f,0x58,0xc2] +; FMACALL64-NEXT: retq ## encoding: [0xc3] ; ; AVX512-LABEL: test_f32_reassoc: ; AVX512: ## %bb.0: @@ -1523,6 +1529,12 @@ define <2 x double> @test_v2f64_reassoc(<2 x double> %a, <2 x double> %b, <2 x d ; FMA32-NEXT: ## xmm0 = (xmm1 * xmm0) + xmm2 ; FMA32-NEXT: retl ## encoding: [0xc3] ; +; FMACALL32-LABEL: test_v2f64_reassoc: +; FMACALL32: ## %bb.0: +; FMACALL32-NEXT: vmulpd %xmm1, %xmm0, %xmm0 ## encoding: [0xc5,0xf9,0x59,0xc1] +; FMACALL32-NEXT: vaddpd %xmm2, %xmm0, %xmm0 ## encoding: [0xc5,0xf9,0x58,0xc2] +; FMACALL32-NEXT: retl ## encoding: [0xc3] +; ; FMA64-LABEL: test_v2f64_reassoc: ; FMA64: ## %bb.0: ; FMA64-NEXT: vfmadd213pd %xmm2, %xmm1, %xmm0 ## encoding: [0xc4,0xe2,0xf1,0xa8,0xc2] @@ -1531,37 +1543,8 @@ define <2 x double> @test_v2f64_reassoc(<2 x double> %a, <2 x double> %b, <2 x d ; ; FMACALL64-LABEL: test_v2f64_reassoc: ; FMACALL64: ## %bb.0: -; FMACALL64-NEXT: subq $72, %rsp ## encoding: [0x48,0x83,0xec,0x48] -; FMACALL64-NEXT: movaps %xmm2, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill -; FMACALL64-NEXT: ## encoding: [0x0f,0x29,0x54,0x24,0x20] -; FMACALL64-NEXT: movaps %xmm1, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill -; FMACALL64-NEXT: ## encoding: [0x0f,0x29,0x4c,0x24,0x10] -; FMACALL64-NEXT: movaps %xmm0, (%rsp) ## 16-byte Spill -; FMACALL64-NEXT: ## encoding: [0x0f,0x29,0x04,0x24] -; FMACALL64-NEXT: callq _fma ## encoding: [0xe8,A,A,A,A] -; FMACALL64-NEXT: ## fixup A - offset: 1, value: _fma-4, kind: reloc_branch_4byte_pcrel -; FMACALL64-NEXT: movaps %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) ## 16-byte Spill -; FMACALL64-NEXT: ## encoding: [0x0f,0x29,0x44,0x24,0x30] -; FMACALL64-NEXT: movaps (%rsp), %xmm0 ## 16-byte Reload -; FMACALL64-NEXT: ## encoding: [0x0f,0x28,0x04,0x24] -; FMACALL64-NEXT: movhlps %xmm0, %xmm0 ## encoding: [0x0f,0x12,0xc0] -; FMACALL64-NEXT: ## xmm0 = xmm0[1,1] -; FMACALL64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 ## 16-byte Reload -; FMACALL64-NEXT: ## encoding: [0x0f,0x28,0x4c,0x24,0x10] -; FMACALL64-NEXT: movhlps %xmm1, %xmm1 ## encoding: [0x0f,0x12,0xc9] -; FMACALL64-NEXT: ## xmm1 = xmm1[1,1] -; FMACALL64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm2 ## 16-byte Reload -; FMACALL64-NEXT: ## encoding: [0x0f,0x28,0x54,0x24,0x20] -; FMACALL64-NEXT: movhlps %xmm2, %xmm2 ## encoding: [0x0f,0x12,0xd2] -; FMACALL64-NEXT: ## xmm2 = xmm2[1,1] -; FMACALL64-NEXT: callq _fma ## encoding: [0xe8,A,A,A,A] -; FMACALL64-NEXT: ## fixup A - offset: 1, value: _fma-4, kind: reloc_branch_4byte_pcrel -; FMACALL64-NEXT: movaps {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 ## 16-byte Reload -; FMACALL64-NEXT: ## encoding: [0x0f,0x28,0x4c,0x24,0x30] -; FMACALL64-NEXT: movlhps %xmm0, %xmm1 ## encoding: [0x0f,0x16,0xc8] -; FMACALL64-NEXT: ## xmm1 = xmm1[0],xmm0[0] -; FMACALL64-NEXT: movaps %xmm1, %xmm0 ## encoding: [0x0f,0x28,0xc1] -; FMACALL64-NEXT: addq $72, %rsp ## encoding: [0x48,0x83,0xc4,0x48] +; FMACALL64-NEXT: mulpd %xmm1, %xmm0 ## encoding: [0x66,0x0f,0x59,0xc1] +; FMACALL64-NEXT: addpd %xmm2, %xmm0 ## encoding: [0x66,0x0f,0x58,0xc2] ; FMACALL64-NEXT: retq ## encoding: [0xc3] ; ; AVX512-LABEL: test_v2f64_reassoc: @@ -1575,41 +1558,6 @@ define <2 x double> @test_v2f64_reassoc(<2 x double> %a, <2 x double> %b, <2 x d ; AVX512VL-NEXT: vfmadd213pd %xmm2, %xmm1, %xmm0 ## EVEX TO VEX Compression encoding: [0xc4,0xe2,0xf1,0xa8,0xc2] ; AVX512VL-NEXT: ## xmm0 = (xmm1 * xmm0) + xmm2 ; AVX512VL-NEXT: retq ## encoding: [0xc3] -; -; FMACALL32_BDVER2-LABEL: test_v2f64_reassoc: -; FMACALL32_BDVER2: ## %bb.0: -; FMACALL32_BDVER2-NEXT: subl $108, %esp ## encoding: [0x83,0xec,0x6c] -; FMACALL32_BDVER2-NEXT: vmovaps %xmm0, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill -; FMACALL32_BDVER2-NEXT: ## encoding: [0xc5,0xf8,0x29,0x44,0x24,0x50] -; FMACALL32_BDVER2-NEXT: vmovlhps %xmm1, %xmm0, %xmm0 ## encoding: [0xc5,0xf8,0x16,0xc1] -; FMACALL32_BDVER2-NEXT: ## xmm0 = xmm0[0],xmm1[0] -; FMACALL32_BDVER2-NEXT: vmovaps %xmm2, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill -; FMACALL32_BDVER2-NEXT: ## encoding: [0xc5,0xf8,0x29,0x54,0x24,0x30] -; FMACALL32_BDVER2-NEXT: vmovaps %xmm1, {{[-0-9]+}}(%e{{[sb]}}p) ## 16-byte Spill -; FMACALL32_BDVER2-NEXT: ## encoding: [0xc5,0xf8,0x29,0x4c,0x24,0x40] -; FMACALL32_BDVER2-NEXT: vmovlps %xmm2, {{[0-9]+}}(%esp) ## encoding: [0xc5,0xf8,0x13,0x54,0x24,0x10] -; FMACALL32_BDVER2-NEXT: vmovups %xmm0, (%esp) ## encoding: [0xc5,0xf8,0x11,0x04,0x24] -; FMACALL32_BDVER2-NEXT: calll _fma ## encoding: [0xe8,A,A,A,A] -; FMACALL32_BDVER2-NEXT: ## fixup A - offset: 1, value: _fma-4, kind: FK_PCRel_4 -; FMACALL32_BDVER2-NEXT: vmovaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload -; FMACALL32_BDVER2-NEXT: ## encoding: [0xc5,0xf8,0x28,0x44,0x24,0x30] -; FMACALL32_BDVER2-NEXT: vmovhps %xmm0, {{[0-9]+}}(%esp) ## encoding: [0xc5,0xf8,0x17,0x44,0x24,0x10] -; FMACALL32_BDVER2-NEXT: vmovaps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0 ## 16-byte Reload -; FMACALL32_BDVER2-NEXT: ## encoding: [0xc5,0xf8,0x28,0x44,0x24,0x40] -; FMACALL32_BDVER2-NEXT: vmovlps {{[-0-9]+}}(%e{{[sb]}}p), %xmm0, %xmm0 ## 16-byte Folded Reload -; FMACALL32_BDVER2-NEXT: ## encoding: [0xc5,0xf8,0x12,0x44,0x24,0x58] -; FMACALL32_BDVER2-NEXT: ## xmm0 = mem[0,1],xmm0[2,3] -; FMACALL32_BDVER2-NEXT: vmovups %xmm0, (%esp) ## encoding: [0xc5,0xf8,0x11,0x04,0x24] -; FMACALL32_BDVER2-NEXT: fstpl {{[0-9]+}}(%esp) ## encoding: [0xdd,0x5c,0x24,0x28] -; FMACALL32_BDVER2-NEXT: calll _fma ## encoding: [0xe8,A,A,A,A] -; FMACALL32_BDVER2-NEXT: ## fixup A - offset: 1, value: _fma-4, kind: FK_PCRel_4 -; FMACALL32_BDVER2-NEXT: fstpl {{[0-9]+}}(%esp) ## encoding: [0xdd,0x5c,0x24,0x20] -; FMACALL32_BDVER2-NEXT: vmovsd {{[0-9]+}}(%esp), %xmm0 ## encoding: [0xc5,0xfb,0x10,0x44,0x24,0x28] -; FMACALL32_BDVER2-NEXT: ## xmm0 = mem[0],zero -; FMACALL32_BDVER2-NEXT: vmovhps {{[0-9]+}}(%esp), %xmm0, %xmm0 ## encoding: [0xc5,0xf8,0x16,0x44,0x24,0x20] -; FMACALL32_BDVER2-NEXT: ## xmm0 = xmm0[0,1],mem[0,1] -; FMACALL32_BDVER2-NEXT: addl $108, %esp ## encoding: [0x83,0xc4,0x6c] -; FMACALL32_BDVER2-NEXT: retl ## encoding: [0xc3] %call = call reassoc <2 x double> @llvm.fma.v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c) ret <2 x double> %call } From 7dfff42f019583076c55993d30a63889613922dd Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Sun, 19 Jul 2020 10:50:51 -0400 Subject: [PATCH 752/771] Silencing some 'logical operation on address of string constant diagnostics; NFC --- clang-tools-extra/clangd/CompileCommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index f6210a43b34eb..6df29bd823196 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -354,7 +354,7 @@ llvm::ArrayRef ArgStripper::rulesFor(llvm::StringRef Arg) { #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELP, METAVAR, VALUES) \ - if (DriverID::OPT_##ALIAS != DriverID::OPT_INVALID && ALIASARGS == nullptr) \ + if (DriverID::OPT_##ALIAS != DriverID::OPT_INVALID && !ALIASARGS) \ AddAlias(DriverID::OPT_##ID, DriverID::OPT_##ALIAS); \ Prefixes[DriverID::OPT_##ID] = PREFIX; #include "clang/Driver/Options.inc" From b79ca34530e88c3a13a9c7afb1df42d7a622e3dd Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Sun, 19 Jul 2020 11:12:39 -0400 Subject: [PATCH 753/771] Revert 7dfff42f019583076c55993d30a63889613922dd as it broke non-Windows builds. --- clang-tools-extra/clangd/CompileCommands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/CompileCommands.cpp b/clang-tools-extra/clangd/CompileCommands.cpp index 6df29bd823196..f6210a43b34eb 100644 --- a/clang-tools-extra/clangd/CompileCommands.cpp +++ b/clang-tools-extra/clangd/CompileCommands.cpp @@ -354,7 +354,7 @@ llvm::ArrayRef ArgStripper::rulesFor(llvm::StringRef Arg) { #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ HELP, METAVAR, VALUES) \ - if (DriverID::OPT_##ALIAS != DriverID::OPT_INVALID && !ALIASARGS) \ + if (DriverID::OPT_##ALIAS != DriverID::OPT_INVALID && ALIASARGS == nullptr) \ AddAlias(DriverID::OPT_##ID, DriverID::OPT_##ALIAS); \ Prefixes[DriverID::OPT_##ID] = PREFIX; #include "clang/Driver/Options.inc" From 97914164f8454e745219566d58479b5762cccd51 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Sun, 19 Jul 2020 11:19:48 -0400 Subject: [PATCH 754/771] Silence a "logical operation on address of string constant" via CMake instead. --- clang-tools-extra/clangd/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt index b3002b1d56981..8db6656e5291a 100644 --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -28,6 +28,10 @@ set(LLVM_LINK_COMPONENTS Option ) +if(MSVC AND NOT CLANG_CL) + set_source_files_properties(CompileCommands.cpp PROPERTIES COMPILE_FLAGS -wd4130) # disables C4130: logical operation on address of string constant +endif() + add_clang_library(clangDaemon AST.cpp ClangdLSPServer.cpp From 2d6ecfa168c2d36ac88efc854f19b05d1c540ded Mon Sep 17 00:00:00 2001 From: Wenlei He Date: Fri, 17 Jul 2020 16:35:56 -0700 Subject: [PATCH 755/771] [InlineAdvisor] New inliner advisor to replay inlining from optimization remarks Summary: This change added a new inline advisor that takes optimization remarks from previous inlining as input, and provides the decision as advice so current inlining can replay inline decisions of a different compilation. Dwarf inline stack with line and discriminator is used as anchor for call sites including call context. The change can be useful for Inliner tuning as it provides a channel to allow external input for tweaking inline decisions. Existing alternatives like alwaysinline attribute is per-function, not per-callsite. Per-callsite inline intrinsic can be another solution (not yet existing), but it's intrusive to implement and also does not differentiate call context. A switch -sample-profile-inline-replay= is added to hook up the new inline advisor with SampleProfileLoader's inline decision for replay. Since SampleProfileLoader does top-down inlining, inline decision can be specialized for each call context, hence we should be able to replay inlining accurately. However with a bottom-up inliner like CGSCC inlining, the replay can be limited due to lack of specialization for different call context. Apart from that limitation, the new inline advisor can still be used by regular CGSCC inliner later if needed for tuning purpose. Subscribers: mgorny, aprantl, hiraditya, llvm-commits Tags: #llvm Resubmit for https://reviews.llvm.org/D84086 --- llvm/include/llvm/Analysis/InlineAdvisor.h | 3 + .../llvm/Analysis/ReplayInlineAdvisor.h | 37 ++++++ llvm/lib/Analysis/CMakeLists.txt | 1 + llvm/lib/Analysis/InlineAdvisor.cpp | 25 ++++ llvm/lib/Analysis/ReplayInlineAdvisor.cpp | 61 +++++++++ llvm/lib/Transforms/IPO/SampleProfile.cpp | 37 +++++- .../SampleProfile/Inputs/inline-replay.txt | 2 + .../Transforms/SampleProfile/inline-replay.ll | 122 ++++++++++++++++++ 8 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 llvm/include/llvm/Analysis/ReplayInlineAdvisor.h create mode 100644 llvm/lib/Analysis/ReplayInlineAdvisor.cpp create mode 100644 llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt create mode 100644 llvm/test/Transforms/SampleProfile/inline-replay.ll diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h index 3480d93385a8e..991c1455cc033 100644 --- a/llvm/include/llvm/Analysis/InlineAdvisor.h +++ b/llvm/include/llvm/Analysis/InlineAdvisor.h @@ -226,6 +226,9 @@ void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, bool ForProfileContext = false, const char *PassName = nullptr); +/// get call site location as string +std::string getCallSiteLocation(DebugLoc DLoc); + /// Add location info to ORE message. void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc); diff --git a/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h b/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h new file mode 100644 index 0000000000000..e312d59a9f87b --- /dev/null +++ b/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h @@ -0,0 +1,37 @@ +//===- ReplayInlineAdvisor.h - Replay Inline Advisor interface -*- C++ --*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +#ifndef LLVM_REPLAYINLINEADVISOR_H_ +#define LLVM_REPLAYINLINEADVISOR_H_ + +#include "llvm/ADT/StringSet.h" +#include "llvm/Analysis/InlineAdvisor.h" +#include "llvm/IR/LLVMContext.h" + +namespace llvm { +class BasicBlock; +class CallBase; +class Function; +class Module; +class OptimizationRemarkEmitter; + +/// Replay inline advisor that uses optimization remarks from inlining of +/// previous build to guide current inlining. This is useful for inliner tuning. +class ReplayInlineAdvisor : public InlineAdvisor { +public: + ReplayInlineAdvisor(FunctionAnalysisManager &FAM, LLVMContext &Context, + StringRef RemarksFile); + std::unique_ptr getAdvice(CallBase &CB) override; + bool areReplayRemarksLoaded() const { return HasReplayRemarks; } + +private: + StringSet<> InlineSitesFromRemarks; + bool HasReplayRemarks = false; +}; +} // namespace llvm +#endif // LLVM_REPLAYINLINEADVISOR_H_ \ No newline at end of file diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 703623396d96a..8f10bac588e52 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -117,6 +117,7 @@ add_llvm_component_library(LLVMAnalysis RegionInfo.cpp RegionPass.cpp RegionPrinter.cpp + ReplayInlineAdvisor.cpp ScalarEvolution.cpp ScalarEvolutionAliasAnalysis.cpp ScalarEvolutionDivision.cpp diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp index e18f681278d3a..497363a5cdf63 100644 --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -365,6 +365,31 @@ llvm::shouldInline(CallBase &CB, return IC; } +std::string llvm::getCallSiteLocation(DebugLoc DLoc) { + std::ostringstream CallSiteLoc; + bool First = true; + for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) { + if (!First) + CallSiteLoc << " @ "; + // Note that negative line offset is actually possible, but we use + // unsigned int to match line offset representation in remarks so + // it's directly consumable by relay advisor. + uint32_t Offset = + DIL->getLine() - DIL->getScope()->getSubprogram()->getLine(); + uint32_t Discriminator = DIL->getBaseDiscriminator(); + StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName(); + if (Name.empty()) + Name = DIL->getScope()->getSubprogram()->getName(); + CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset); + if (Discriminator) { + CallSiteLoc << "." << llvm::utostr(Discriminator); + } + First = false; + } + + return CallSiteLoc.str(); +} + void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) { if (!DLoc.get()) return; diff --git a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp new file mode 100644 index 0000000000000..c12b58021a606 --- /dev/null +++ b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp @@ -0,0 +1,61 @@ +//===- ReplayInlineAdvisor.cpp - Replay InlineAdvisor ---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements ReplayInlineAdvisor that replays inline decision based +// on previous inline remarks from optimization remark log. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/InlineAdvisor.h" +#include "llvm/Analysis/ReplayInlineAdvisor.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/LineIterator.h" + +using namespace llvm; + +#define DEBUG_TYPE "inline-replay" + +ReplayInlineAdvisor::ReplayInlineAdvisor(FunctionAnalysisManager &FAM, + LLVMContext &Context, + StringRef RemarksFile) + : InlineAdvisor(FAM), HasReplayRemarks(false) { + auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(RemarksFile); + std::error_code EC = BufferOrErr.getError(); + if (EC) { + Context.emitError("Could not open remarks file: " + EC.message()); + return; + } + + // Example for inline remarks to parse: + // _Z3subii inlined into main [details] at callsite sum:1 @ main:3.1 + // We use the callsite string after `at callsite` to replay inlining. + line_iterator LineIt(*BufferOrErr.get(), /*SkipBlanks=*/true); + for (; !LineIt.is_at_eof(); ++LineIt) { + StringRef Line = *LineIt; + auto Pair = Line.split(" at callsite "); + if (Pair.second.empty()) + continue; + InlineSitesFromRemarks.insert(Pair.second); + } + HasReplayRemarks = true; +} + +std::unique_ptr ReplayInlineAdvisor::getAdvice(CallBase &CB) { + assert(HasReplayRemarks); + + Function &Caller = *CB.getCaller(); + auto &ORE = FAM.getResult(Caller); + + if (InlineSitesFromRemarks.empty()) + return std::make_unique(this, CB, ORE, false); + + StringRef CallSiteLoc = getCallSiteLocation(CB.getDebugLoc()); + bool InlineRecommended = InlineSitesFromRemarks.count(CallSiteLoc) > 0; + return std::make_unique(this, CB, ORE, InlineRecommended); +} diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index b6871e260532d..7b5fc030cf88c 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -43,6 +43,7 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ProfileSummaryInfo.h" +#include "llvm/Analysis/ReplayInlineAdvisor.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/BasicBlock.h" @@ -170,6 +171,13 @@ static cl::opt SampleColdCallSiteThreshold( "sample-profile-cold-inline-threshold", cl::Hidden, cl::init(45), cl::desc("Threshold for inlining cold callsites")); +static cl::opt ProfileInlineReplayFile( + "sample-profile-inline-replay", cl::init(""), cl::value_desc("filename"), + cl::desc( + "Optimization remarks file containing inline remarks to be replayed " + "by inlining from sample profile loader."), + cl::Hidden); + namespace { using BlockWeightMap = DenseMap; @@ -319,7 +327,7 @@ class SampleProfileLoader { RemappingFilename(std::string(RemapName)), IsThinLTOPreLink(IsThinLTOPreLink) {} - bool doInitialization(Module &M); + bool doInitialization(Module &M, FunctionAnalysisManager *FAM = nullptr); bool runOnModule(Module &M, ModuleAnalysisManager *AM, ProfileSummaryInfo *_PSI, CallGraph *CG); @@ -473,6 +481,9 @@ class SampleProfileLoader { // overriden by -profile-sample-accurate or profile-sample-accurate // attribute. bool ProfAccForSymsInList; + + // External inline advisor used to replay inline decision from remarks. + std::unique_ptr ExternalInlineAdvisor; }; class SampleProfileLoaderLegacyPass : public ModulePass { @@ -898,6 +909,16 @@ SampleProfileLoader::findFunctionSamples(const Instruction &Inst) const { } bool SampleProfileLoader::inlineCallInstruction(CallBase &CB) { + if (ExternalInlineAdvisor) { + auto Advice = ExternalInlineAdvisor->getAdvice(CB); + if (!Advice->isInliningRecommended()) { + Advice->recordUnattemptedInlining(); + return false; + } + // Dummy record, we don't use it for replay. + Advice->recordInlining(); + } + Function *CalledFunction = CB.getCalledFunction(); assert(CalledFunction); DebugLoc DLoc = CB.getDebugLoc(); @@ -1005,7 +1026,7 @@ bool SampleProfileLoader::inlineHotFunctions( } } } - if (Hot) { + if (Hot || ExternalInlineAdvisor) { CIS.insert(CIS.begin(), AllCandidates.begin(), AllCandidates.end()); emitOptimizationRemarksForInlineCandidates(AllCandidates, F, true); } else { @@ -1818,7 +1839,8 @@ SampleProfileLoader::buildFunctionOrder(Module &M, CallGraph *CG) { return FunctionOrderList; } -bool SampleProfileLoader::doInitialization(Module &M) { +bool SampleProfileLoader::doInitialization(Module &M, + FunctionAnalysisManager *FAM) { auto &Ctx = M.getContext(); std::unique_ptr RemapReader; @@ -1843,6 +1865,13 @@ bool SampleProfileLoader::doInitialization(Module &M) { NamesInProfile.insert(NameTable->begin(), NameTable->end()); } + if (FAM && !ProfileInlineReplayFile.empty()) { + ExternalInlineAdvisor = std::make_unique( + *FAM, Ctx, ProfileInlineReplayFile); + if (!ExternalInlineAdvisor->areReplayRemarksLoaded()) + ExternalInlineAdvisor.reset(); + } + return true; } @@ -1995,7 +2024,7 @@ PreservedAnalyses SampleProfileLoaderPass::run(Module &M, : ProfileRemappingFileName, IsThinLTOPreLink, GetAssumptionCache, GetTTI, GetTLI); - if (!SampleLoader.doInitialization(M)) + if (!SampleLoader.doInitialization(M, &FAM)) return PreservedAnalyses::all(); ProfileSummaryInfo *PSI = &AM.getResult(M); diff --git a/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt b/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt new file mode 100644 index 0000000000000..6842845d56554 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt @@ -0,0 +1,2 @@ +remark: calls.cc:10:0: _Z3sumii inlined into main to match profiling context with (cost=45, threshold=337) at callsite main:3.1 +remark: calls.cc:4:0: _Z3subii inlined into main to match profiling context with (cost=-5, threshold=337) at callsite _Z3sumii:1 @ main:3.1 diff --git a/llvm/test/Transforms/SampleProfile/inline-replay.ll b/llvm/test/Transforms/SampleProfile/inline-replay.ll new file mode 100644 index 0000000000000..ecf6f51850f26 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/inline-replay.ll @@ -0,0 +1,122 @@ +;; Note that this needs new pass manager for now. Passing `-sample-profile-inline-replay` to legacy pass manager is a no-op. + +;; Check baseline inline decisions +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline-topdown.prof -sample-profile-merge-inlinee -sample-profile-top-down-load -pass-remarks=inline -S 2>&1 | FileCheck -check-prefix=DEFAULT %s + +;; Check replay inline decisions +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline-topdown.prof -sample-profile-inline-replay=%S/Inputs/inline-replay.txt -sample-profile-merge-inlinee -sample-profile-top-down-load -pass-remarks=inline -S 2>&1 | FileCheck -check-prefix=REPLAY %s + +@.str = private unnamed_addr constant [11 x i8] c"sum is %d\0A\00", align 1 + +define i32 @_Z3sumii(i32 %x, i32 %y) #0 !dbg !6 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %tmp = load i32, i32* %x.addr, align 4, !dbg !8 + %tmp1 = load i32, i32* %y.addr, align 4, !dbg !8 + %add = add nsw i32 %tmp, %tmp1, !dbg !8 + %tmp2 = load i32, i32* %x.addr, align 4, !dbg !8 + %tmp3 = load i32, i32* %y.addr, align 4, !dbg !8 + %call = call i32 @_Z3subii(i32 %tmp2, i32 %tmp3), !dbg !8 + ret i32 %add, !dbg !8 +} + +define i32 @_Z3subii(i32 %x, i32 %y) #0 !dbg !9 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %tmp = load i32, i32* %x.addr, align 4, !dbg !10 + %tmp1 = load i32, i32* %y.addr, align 4, !dbg !10 + %add = sub nsw i32 %tmp, %tmp1, !dbg !10 + ret i32 %add, !dbg !11 +} + +define i32 @main() #0 !dbg !12 { +entry: + %retval = alloca i32, align 4 + %s = alloca i32, align 4 + %i = alloca i32, align 4 + store i32 0, i32* %retval + store i32 0, i32* %i, align 4, !dbg !13 + br label %while.cond, !dbg !14 + +while.cond: ; preds = %if.end, %entry + %tmp = load i32, i32* %i, align 4, !dbg !15 + %inc = add nsw i32 %tmp, 1, !dbg !15 + store i32 %inc, i32* %i, align 4, !dbg !15 + %cmp = icmp slt i32 %tmp, 400000000, !dbg !15 + br i1 %cmp, label %while.body, label %while.end, !dbg !15 + +while.body: ; preds = %while.cond + %tmp1 = load i32, i32* %i, align 4, !dbg !17 + %cmp1 = icmp ne i32 %tmp1, 100, !dbg !17 + br i1 %cmp1, label %if.then, label %if.else, !dbg !17 + +if.then: ; preds = %while.body + %tmp2 = load i32, i32* %i, align 4, !dbg !19 + %tmp3 = load i32, i32* %s, align 4, !dbg !19 + %call = call i32 @_Z3sumii(i32 %tmp2, i32 %tmp3), !dbg !19 + store i32 %call, i32* %s, align 4, !dbg !19 + br label %if.end, !dbg !19 + +if.else: ; preds = %while.body + store i32 30, i32* %s, align 4, !dbg !21 + br label %if.end + +if.end: ; preds = %if.else, %if.then + br label %while.cond, !dbg !23 + +while.end: ; preds = %while.cond + %tmp4 = load i32, i32* %s, align 4, !dbg !25 + %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i32 %tmp4), !dbg !25 + ret i32 0, !dbg !26 +} + +declare i32 @printf(i8*, ...) + +attributes #0 = { "use-sample-profile" } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.5 ", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!1 = !DIFile(filename: "calls.cc", directory: ".") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 1, !"Debug Info Version", i32 3} +!5 = !{!"clang version 3.5 "} +!6 = distinct !DISubprogram(name: "sum", linkageName: "_Z3sumii", scope: !1, file: !1, line: 3, type: !7, scopeLine: 3, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!7 = !DISubroutineType(types: !2) +!8 = !DILocation(line: 4, scope: !6) +!9 = distinct !DISubprogram(name: "sub", linkageName: "_Z3subii", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!10 = !DILocation(line: 20, scope: !9) +!11 = !DILocation(line: 21, scope: !9) +!12 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 7, type: !7, scopeLine: 7, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!13 = !DILocation(line: 8, scope: !12) +!14 = !DILocation(line: 9, scope: !12) +!15 = !DILocation(line: 9, scope: !16) +!16 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 2) +!17 = !DILocation(line: 10, scope: !18) +!18 = distinct !DILexicalBlock(scope: !12, file: !1, line: 10) +!19 = !DILocation(line: 10, scope: !20) +!20 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 2) +!21 = !DILocation(line: 10, scope: !22) +!22 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 4) +!23 = !DILocation(line: 10, scope: !24) +!24 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 6) +!25 = !DILocation(line: 11, scope: !12) +!26 = !DILocation(line: 12, scope: !12) + + +; DEFAULT: _Z3sumii inlined into main +; DEFAULT: _Z3subii inlined into _Z3sumii +; DEFAULT-NOT: _Z3subii inlined into main + +; REPLAY: _Z3sumii inlined into main +; REPLAY: _Z3subii inlined into main +; REPLA-NOT: _Z3subii inlined into _Z3sumii From d41d952be9773ad79fe2563074c612c1f810b83c Mon Sep 17 00:00:00 2001 From: Wenlei He Date: Sun, 19 Jul 2020 08:49:04 -0700 Subject: [PATCH 756/771] Revert "[InlineAdvisor] New inliner advisor to replay inlining from optimization remarks" This reverts commit 2d6ecfa168c2d36ac88efc854f19b05d1c540ded. --- llvm/include/llvm/Analysis/InlineAdvisor.h | 3 - .../llvm/Analysis/ReplayInlineAdvisor.h | 37 ------ llvm/lib/Analysis/CMakeLists.txt | 1 - llvm/lib/Analysis/InlineAdvisor.cpp | 25 ---- llvm/lib/Analysis/ReplayInlineAdvisor.cpp | 61 --------- llvm/lib/Transforms/IPO/SampleProfile.cpp | 37 +----- .../SampleProfile/Inputs/inline-replay.txt | 2 - .../Transforms/SampleProfile/inline-replay.ll | 122 ------------------ 8 files changed, 4 insertions(+), 284 deletions(-) delete mode 100644 llvm/include/llvm/Analysis/ReplayInlineAdvisor.h delete mode 100644 llvm/lib/Analysis/ReplayInlineAdvisor.cpp delete mode 100644 llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt delete mode 100644 llvm/test/Transforms/SampleProfile/inline-replay.ll diff --git a/llvm/include/llvm/Analysis/InlineAdvisor.h b/llvm/include/llvm/Analysis/InlineAdvisor.h index 991c1455cc033..3480d93385a8e 100644 --- a/llvm/include/llvm/Analysis/InlineAdvisor.h +++ b/llvm/include/llvm/Analysis/InlineAdvisor.h @@ -226,9 +226,6 @@ void emitInlinedInto(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, bool ForProfileContext = false, const char *PassName = nullptr); -/// get call site location as string -std::string getCallSiteLocation(DebugLoc DLoc); - /// Add location info to ORE message. void addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc); diff --git a/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h b/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h deleted file mode 100644 index e312d59a9f87b..0000000000000 --- a/llvm/include/llvm/Analysis/ReplayInlineAdvisor.h +++ /dev/null @@ -1,37 +0,0 @@ -//===- ReplayInlineAdvisor.h - Replay Inline Advisor interface -*- C++ --*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -#ifndef LLVM_REPLAYINLINEADVISOR_H_ -#define LLVM_REPLAYINLINEADVISOR_H_ - -#include "llvm/ADT/StringSet.h" -#include "llvm/Analysis/InlineAdvisor.h" -#include "llvm/IR/LLVMContext.h" - -namespace llvm { -class BasicBlock; -class CallBase; -class Function; -class Module; -class OptimizationRemarkEmitter; - -/// Replay inline advisor that uses optimization remarks from inlining of -/// previous build to guide current inlining. This is useful for inliner tuning. -class ReplayInlineAdvisor : public InlineAdvisor { -public: - ReplayInlineAdvisor(FunctionAnalysisManager &FAM, LLVMContext &Context, - StringRef RemarksFile); - std::unique_ptr getAdvice(CallBase &CB) override; - bool areReplayRemarksLoaded() const { return HasReplayRemarks; } - -private: - StringSet<> InlineSitesFromRemarks; - bool HasReplayRemarks = false; -}; -} // namespace llvm -#endif // LLVM_REPLAYINLINEADVISOR_H_ \ No newline at end of file diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt index 8f10bac588e52..703623396d96a 100644 --- a/llvm/lib/Analysis/CMakeLists.txt +++ b/llvm/lib/Analysis/CMakeLists.txt @@ -117,7 +117,6 @@ add_llvm_component_library(LLVMAnalysis RegionInfo.cpp RegionPass.cpp RegionPrinter.cpp - ReplayInlineAdvisor.cpp ScalarEvolution.cpp ScalarEvolutionAliasAnalysis.cpp ScalarEvolutionDivision.cpp diff --git a/llvm/lib/Analysis/InlineAdvisor.cpp b/llvm/lib/Analysis/InlineAdvisor.cpp index 497363a5cdf63..e18f681278d3a 100644 --- a/llvm/lib/Analysis/InlineAdvisor.cpp +++ b/llvm/lib/Analysis/InlineAdvisor.cpp @@ -365,31 +365,6 @@ llvm::shouldInline(CallBase &CB, return IC; } -std::string llvm::getCallSiteLocation(DebugLoc DLoc) { - std::ostringstream CallSiteLoc; - bool First = true; - for (DILocation *DIL = DLoc.get(); DIL; DIL = DIL->getInlinedAt()) { - if (!First) - CallSiteLoc << " @ "; - // Note that negative line offset is actually possible, but we use - // unsigned int to match line offset representation in remarks so - // it's directly consumable by relay advisor. - uint32_t Offset = - DIL->getLine() - DIL->getScope()->getSubprogram()->getLine(); - uint32_t Discriminator = DIL->getBaseDiscriminator(); - StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName(); - if (Name.empty()) - Name = DIL->getScope()->getSubprogram()->getName(); - CallSiteLoc << Name.str() << ":" << llvm::utostr(Offset); - if (Discriminator) { - CallSiteLoc << "." << llvm::utostr(Discriminator); - } - First = false; - } - - return CallSiteLoc.str(); -} - void llvm::addLocationToRemarks(OptimizationRemark &Remark, DebugLoc DLoc) { if (!DLoc.get()) return; diff --git a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp b/llvm/lib/Analysis/ReplayInlineAdvisor.cpp deleted file mode 100644 index c12b58021a606..0000000000000 --- a/llvm/lib/Analysis/ReplayInlineAdvisor.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//===- ReplayInlineAdvisor.cpp - Replay InlineAdvisor ---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements ReplayInlineAdvisor that replays inline decision based -// on previous inline remarks from optimization remark log. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Analysis/InlineAdvisor.h" -#include "llvm/Analysis/ReplayInlineAdvisor.h" -#include "llvm/IR/DebugInfoMetadata.h" -#include "llvm/IR/Instructions.h" -#include "llvm/Support/LineIterator.h" - -using namespace llvm; - -#define DEBUG_TYPE "inline-replay" - -ReplayInlineAdvisor::ReplayInlineAdvisor(FunctionAnalysisManager &FAM, - LLVMContext &Context, - StringRef RemarksFile) - : InlineAdvisor(FAM), HasReplayRemarks(false) { - auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(RemarksFile); - std::error_code EC = BufferOrErr.getError(); - if (EC) { - Context.emitError("Could not open remarks file: " + EC.message()); - return; - } - - // Example for inline remarks to parse: - // _Z3subii inlined into main [details] at callsite sum:1 @ main:3.1 - // We use the callsite string after `at callsite` to replay inlining. - line_iterator LineIt(*BufferOrErr.get(), /*SkipBlanks=*/true); - for (; !LineIt.is_at_eof(); ++LineIt) { - StringRef Line = *LineIt; - auto Pair = Line.split(" at callsite "); - if (Pair.second.empty()) - continue; - InlineSitesFromRemarks.insert(Pair.second); - } - HasReplayRemarks = true; -} - -std::unique_ptr ReplayInlineAdvisor::getAdvice(CallBase &CB) { - assert(HasReplayRemarks); - - Function &Caller = *CB.getCaller(); - auto &ORE = FAM.getResult(Caller); - - if (InlineSitesFromRemarks.empty()) - return std::make_unique(this, CB, ORE, false); - - StringRef CallSiteLoc = getCallSiteLocation(CB.getDebugLoc()); - bool InlineRecommended = InlineSitesFromRemarks.count(CallSiteLoc) > 0; - return std::make_unique(this, CB, ORE, InlineRecommended); -} diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index 7b5fc030cf88c..b6871e260532d 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -43,7 +43,6 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ProfileSummaryInfo.h" -#include "llvm/Analysis/ReplayInlineAdvisor.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/BasicBlock.h" @@ -171,13 +170,6 @@ static cl::opt SampleColdCallSiteThreshold( "sample-profile-cold-inline-threshold", cl::Hidden, cl::init(45), cl::desc("Threshold for inlining cold callsites")); -static cl::opt ProfileInlineReplayFile( - "sample-profile-inline-replay", cl::init(""), cl::value_desc("filename"), - cl::desc( - "Optimization remarks file containing inline remarks to be replayed " - "by inlining from sample profile loader."), - cl::Hidden); - namespace { using BlockWeightMap = DenseMap; @@ -327,7 +319,7 @@ class SampleProfileLoader { RemappingFilename(std::string(RemapName)), IsThinLTOPreLink(IsThinLTOPreLink) {} - bool doInitialization(Module &M, FunctionAnalysisManager *FAM = nullptr); + bool doInitialization(Module &M); bool runOnModule(Module &M, ModuleAnalysisManager *AM, ProfileSummaryInfo *_PSI, CallGraph *CG); @@ -481,9 +473,6 @@ class SampleProfileLoader { // overriden by -profile-sample-accurate or profile-sample-accurate // attribute. bool ProfAccForSymsInList; - - // External inline advisor used to replay inline decision from remarks. - std::unique_ptr ExternalInlineAdvisor; }; class SampleProfileLoaderLegacyPass : public ModulePass { @@ -909,16 +898,6 @@ SampleProfileLoader::findFunctionSamples(const Instruction &Inst) const { } bool SampleProfileLoader::inlineCallInstruction(CallBase &CB) { - if (ExternalInlineAdvisor) { - auto Advice = ExternalInlineAdvisor->getAdvice(CB); - if (!Advice->isInliningRecommended()) { - Advice->recordUnattemptedInlining(); - return false; - } - // Dummy record, we don't use it for replay. - Advice->recordInlining(); - } - Function *CalledFunction = CB.getCalledFunction(); assert(CalledFunction); DebugLoc DLoc = CB.getDebugLoc(); @@ -1026,7 +1005,7 @@ bool SampleProfileLoader::inlineHotFunctions( } } } - if (Hot || ExternalInlineAdvisor) { + if (Hot) { CIS.insert(CIS.begin(), AllCandidates.begin(), AllCandidates.end()); emitOptimizationRemarksForInlineCandidates(AllCandidates, F, true); } else { @@ -1839,8 +1818,7 @@ SampleProfileLoader::buildFunctionOrder(Module &M, CallGraph *CG) { return FunctionOrderList; } -bool SampleProfileLoader::doInitialization(Module &M, - FunctionAnalysisManager *FAM) { +bool SampleProfileLoader::doInitialization(Module &M) { auto &Ctx = M.getContext(); std::unique_ptr RemapReader; @@ -1865,13 +1843,6 @@ bool SampleProfileLoader::doInitialization(Module &M, NamesInProfile.insert(NameTable->begin(), NameTable->end()); } - if (FAM && !ProfileInlineReplayFile.empty()) { - ExternalInlineAdvisor = std::make_unique( - *FAM, Ctx, ProfileInlineReplayFile); - if (!ExternalInlineAdvisor->areReplayRemarksLoaded()) - ExternalInlineAdvisor.reset(); - } - return true; } @@ -2024,7 +1995,7 @@ PreservedAnalyses SampleProfileLoaderPass::run(Module &M, : ProfileRemappingFileName, IsThinLTOPreLink, GetAssumptionCache, GetTTI, GetTLI); - if (!SampleLoader.doInitialization(M, &FAM)) + if (!SampleLoader.doInitialization(M)) return PreservedAnalyses::all(); ProfileSummaryInfo *PSI = &AM.getResult(M); diff --git a/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt b/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt deleted file mode 100644 index 6842845d56554..0000000000000 --- a/llvm/test/Transforms/SampleProfile/Inputs/inline-replay.txt +++ /dev/null @@ -1,2 +0,0 @@ -remark: calls.cc:10:0: _Z3sumii inlined into main to match profiling context with (cost=45, threshold=337) at callsite main:3.1 -remark: calls.cc:4:0: _Z3subii inlined into main to match profiling context with (cost=-5, threshold=337) at callsite _Z3sumii:1 @ main:3.1 diff --git a/llvm/test/Transforms/SampleProfile/inline-replay.ll b/llvm/test/Transforms/SampleProfile/inline-replay.ll deleted file mode 100644 index ecf6f51850f26..0000000000000 --- a/llvm/test/Transforms/SampleProfile/inline-replay.ll +++ /dev/null @@ -1,122 +0,0 @@ -;; Note that this needs new pass manager for now. Passing `-sample-profile-inline-replay` to legacy pass manager is a no-op. - -;; Check baseline inline decisions -; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline-topdown.prof -sample-profile-merge-inlinee -sample-profile-top-down-load -pass-remarks=inline -S 2>&1 | FileCheck -check-prefix=DEFAULT %s - -;; Check replay inline decisions -; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline-topdown.prof -sample-profile-inline-replay=%S/Inputs/inline-replay.txt -sample-profile-merge-inlinee -sample-profile-top-down-load -pass-remarks=inline -S 2>&1 | FileCheck -check-prefix=REPLAY %s - -@.str = private unnamed_addr constant [11 x i8] c"sum is %d\0A\00", align 1 - -define i32 @_Z3sumii(i32 %x, i32 %y) #0 !dbg !6 { -entry: - %x.addr = alloca i32, align 4 - %y.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - store i32 %y, i32* %y.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4, !dbg !8 - %tmp1 = load i32, i32* %y.addr, align 4, !dbg !8 - %add = add nsw i32 %tmp, %tmp1, !dbg !8 - %tmp2 = load i32, i32* %x.addr, align 4, !dbg !8 - %tmp3 = load i32, i32* %y.addr, align 4, !dbg !8 - %call = call i32 @_Z3subii(i32 %tmp2, i32 %tmp3), !dbg !8 - ret i32 %add, !dbg !8 -} - -define i32 @_Z3subii(i32 %x, i32 %y) #0 !dbg !9 { -entry: - %x.addr = alloca i32, align 4 - %y.addr = alloca i32, align 4 - store i32 %x, i32* %x.addr, align 4 - store i32 %y, i32* %y.addr, align 4 - %tmp = load i32, i32* %x.addr, align 4, !dbg !10 - %tmp1 = load i32, i32* %y.addr, align 4, !dbg !10 - %add = sub nsw i32 %tmp, %tmp1, !dbg !10 - ret i32 %add, !dbg !11 -} - -define i32 @main() #0 !dbg !12 { -entry: - %retval = alloca i32, align 4 - %s = alloca i32, align 4 - %i = alloca i32, align 4 - store i32 0, i32* %retval - store i32 0, i32* %i, align 4, !dbg !13 - br label %while.cond, !dbg !14 - -while.cond: ; preds = %if.end, %entry - %tmp = load i32, i32* %i, align 4, !dbg !15 - %inc = add nsw i32 %tmp, 1, !dbg !15 - store i32 %inc, i32* %i, align 4, !dbg !15 - %cmp = icmp slt i32 %tmp, 400000000, !dbg !15 - br i1 %cmp, label %while.body, label %while.end, !dbg !15 - -while.body: ; preds = %while.cond - %tmp1 = load i32, i32* %i, align 4, !dbg !17 - %cmp1 = icmp ne i32 %tmp1, 100, !dbg !17 - br i1 %cmp1, label %if.then, label %if.else, !dbg !17 - -if.then: ; preds = %while.body - %tmp2 = load i32, i32* %i, align 4, !dbg !19 - %tmp3 = load i32, i32* %s, align 4, !dbg !19 - %call = call i32 @_Z3sumii(i32 %tmp2, i32 %tmp3), !dbg !19 - store i32 %call, i32* %s, align 4, !dbg !19 - br label %if.end, !dbg !19 - -if.else: ; preds = %while.body - store i32 30, i32* %s, align 4, !dbg !21 - br label %if.end - -if.end: ; preds = %if.else, %if.then - br label %while.cond, !dbg !23 - -while.end: ; preds = %while.cond - %tmp4 = load i32, i32* %s, align 4, !dbg !25 - %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i32 %tmp4), !dbg !25 - ret i32 0, !dbg !26 -} - -declare i32 @printf(i8*, ...) - -attributes #0 = { "use-sample-profile" } - -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!3, !4} -!llvm.ident = !{!5} - -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.5 ", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2) -!1 = !DIFile(filename: "calls.cc", directory: ".") -!2 = !{} -!3 = !{i32 2, !"Dwarf Version", i32 4} -!4 = !{i32 1, !"Debug Info Version", i32 3} -!5 = !{!"clang version 3.5 "} -!6 = distinct !DISubprogram(name: "sum", linkageName: "_Z3sumii", scope: !1, file: !1, line: 3, type: !7, scopeLine: 3, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!7 = !DISubroutineType(types: !2) -!8 = !DILocation(line: 4, scope: !6) -!9 = distinct !DISubprogram(name: "sub", linkageName: "_Z3subii", scope: !1, file: !1, line: 20, type: !7, scopeLine: 20, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!10 = !DILocation(line: 20, scope: !9) -!11 = !DILocation(line: 21, scope: !9) -!12 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 7, type: !7, scopeLine: 7, virtualIndex: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!13 = !DILocation(line: 8, scope: !12) -!14 = !DILocation(line: 9, scope: !12) -!15 = !DILocation(line: 9, scope: !16) -!16 = !DILexicalBlockFile(scope: !12, file: !1, discriminator: 2) -!17 = !DILocation(line: 10, scope: !18) -!18 = distinct !DILexicalBlock(scope: !12, file: !1, line: 10) -!19 = !DILocation(line: 10, scope: !20) -!20 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 2) -!21 = !DILocation(line: 10, scope: !22) -!22 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 4) -!23 = !DILocation(line: 10, scope: !24) -!24 = !DILexicalBlockFile(scope: !18, file: !1, discriminator: 6) -!25 = !DILocation(line: 11, scope: !12) -!26 = !DILocation(line: 12, scope: !12) - - -; DEFAULT: _Z3sumii inlined into main -; DEFAULT: _Z3subii inlined into _Z3sumii -; DEFAULT-NOT: _Z3subii inlined into main - -; REPLAY: _Z3sumii inlined into main -; REPLAY: _Z3subii inlined into main -; REPLA-NOT: _Z3subii inlined into _Z3sumii From 13316a77053514be552a0dad932e3455413b4f82 Mon Sep 17 00:00:00 2001 From: Bruno Ricci Date: Sun, 19 Jul 2020 16:53:59 +0100 Subject: [PATCH 757/771] [clang] Disable a few formatting options for test/ Hopefully this will make the bot a little less noisy. Rationale for each: AlignTrailingComments: We don't want to force-align the various expected-error and friends. CommentPragmas: Tell clang-format to leave the "// CHECK:" and the "// expected-" alone. AlwaysBreakTemplateDeclarations: Templates in tests often have no break between the template-head and the declaration. Differential Revision: https://reviews.llvm.org/D83901 --- clang/test/.clang-format | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/test/.clang-format b/clang/test/.clang-format index 4799b66f3e9a6..a6176c2e00131 100644 --- a/clang/test/.clang-format +++ b/clang/test/.clang-format @@ -1,2 +1,5 @@ BasedOnStyle: LLVM ColumnLimit: 0 +AlignTrailingComments: false +CommentPragmas: "(^ ?CHECK|^ ?expected-)" +AlwaysBreakTemplateDeclarations: No From 89ff9bf061b4985d11cd4785958d8f8156d10f5d Mon Sep 17 00:00:00 2001 From: Bruno Ricci Date: Sun, 19 Jul 2020 17:08:17 +0100 Subject: [PATCH 758/771] [clang] Fix the warning for a non-void consteval function without a return value to actually say "consteval". This warning was modified in 796ed03b8412 to use the term "consteval" for consteval functions. However the warning has never worked as intended since the diagnostic's arguments are used in the wrong order. This was unfortunately missed by 796ed03b8412 since no test did exercise this specific warning. Additionally send the NamedDecl* into the diagnostic instead of just the IdentifierInfo* to correctly work with special names and template arguments. --- clang/lib/Sema/SemaStmt.cpp | 25 ++++++++++--------- .../SemaCXX/constant-expression-cxx11.cpp | 2 +- clang/test/SemaCXX/consteval-return-void.cpp | 20 +++++++++++---- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 73f3183c163f3..948c187804dcc 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3766,25 +3766,26 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } else if (!RetValExp && !HasDependentReturnType) { FunctionDecl *FD = getCurFunctionDecl(); - unsigned DiagID; if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { // C++11 [stmt.return]p2 - DiagID = diag::err_constexpr_return_missing_expr; + Diag(ReturnLoc, diag::err_constexpr_return_missing_expr) + << FD << FD->isConsteval(); FD->setInvalidDecl(); - } else if (getLangOpts().C99) { - // C99 6.8.6.4p1 (ext_ since GCC warns) - DiagID = diag::ext_return_missing_expr; } else { + // C99 6.8.6.4p1 (ext_ since GCC warns) // C90 6.6.6.4p4 - DiagID = diag::warn_return_missing_expr; + unsigned DiagID = getLangOpts().C99 ? diag::ext_return_missing_expr + : diag::warn_return_missing_expr; + // Note that at this point one of getCurFunctionDecl() or + // getCurMethodDecl() must be non-null (see above). + assert((getCurFunctionDecl() || getCurMethodDecl()) && + "Not in a FunctionDecl or ObjCMethodDecl?"); + bool IsMethod = FD == nullptr; + const NamedDecl *ND = + IsMethod ? cast(getCurMethodDecl()) : cast(FD); + Diag(ReturnLoc, DiagID) << ND << IsMethod; } - if (FD) - Diag(ReturnLoc, DiagID) - << FD->getIdentifier() << 0 /*fn*/ << FD->isConsteval(); - else - Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; - Result = ReturnStmt::Create(Context, ReturnLoc, /* RetExpr=*/nullptr, /* NRVOCandidate=*/nullptr); } else { diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 7ff260c37c698..eac0256c4fb21 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -2171,7 +2171,7 @@ namespace PR21859 { template constexpr int FunT1() { return; } // expected-error {{non-void constexpr function 'FunT1' should return a value}} template constexpr int FunT2() { return 0; } template <> constexpr int FunT2() { return 0; } - template <> constexpr int FunT2() { return; } // expected-error {{non-void constexpr function 'FunT2' should return a value}} + template <> constexpr int FunT2() { return; } // expected-error {{non-void constexpr function 'FunT2' should return a value}} } struct InvalidRedef { diff --git a/clang/test/SemaCXX/consteval-return-void.cpp b/clang/test/SemaCXX/consteval-return-void.cpp index a5207f41bf2c7..39e1418306f50 100644 --- a/clang/test/SemaCXX/consteval-return-void.cpp +++ b/clang/test/SemaCXX/consteval-return-void.cpp @@ -1,10 +1,20 @@ // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s -consteval int Fun() { return; } // expected-error {{non-void constexpr function 'Fun' should return a value}} +consteval int Fun() { return; } // expected-error {{non-void consteval function 'Fun' should return a value}} -// FIXME: The diagnostic is wrong; should be "consteval". - -template consteval int FunT1() { return; } // expected-error {{non-void constexpr function 'FunT1' should return a value}} +template consteval int FunT1() { return; } // expected-error {{non-void consteval function 'FunT1' should return a value}} template consteval int FunT2() { return 0; } template <> consteval int FunT2() { return 0; } -template <> consteval int FunT2() { return; } // expected-error {{non-void constexpr function 'FunT2' should return a value}} +template <> consteval int FunT2() { return; } // expected-error {{non-void consteval function 'FunT2' should return a value}} + +enum E {}; + +constexpr E operator+(E,E) { return; } // expected-error {{non-void constexpr function 'operator+' should return a value}} +consteval E operator+(E,E) { return; } // expected-error {{non-void consteval function 'operator+' should return a value}} +template constexpr E operator-(E,E) { return; } // expected-error {{non-void constexpr function 'operator-' should return a value}} +template consteval E operator-(E,E) { return; } // expected-error {{non-void consteval function 'operator-' should return a value}} + +template constexpr E operator*(E,E); +template consteval E operator/(E,E); +template <> constexpr E operator*(E,E) { return; } // expected-error {{non-void constexpr function 'operator*' should return a value}} +template <> consteval E operator/(E,E) { return; } // expected-error {{non-void consteval function 'operator/' should return a value}} From 0a6aee51608df8502d1d20746d011b3024230c9a Mon Sep 17 00:00:00 2001 From: Juneyoung Lee Date: Mon, 20 Jul 2020 01:23:58 +0900 Subject: [PATCH 759/771] [ValueTracking] Add canCreateUndefOrPoison & let canCreatePoison use Operator This patch - adds `canCreateUndefOrPoison` - refactors `canCreatePoison` so it can deal with constantexprs `canCreateUndefOrPoison` will be used at D83926. Reviewed By: nikic, jdoerfert Differential Revision: https://reviews.llvm.org/D84007 --- llvm/include/llvm/Analysis/ValueTracking.h | 24 ++-- llvm/lib/Analysis/ValueTracking.cpp | 70 +++++++---- .../Instrumentation/PoisonChecking.cpp | 2 +- llvm/unittests/Analysis/ValueTrackingTest.cpp | 114 ++++++++++-------- 4 files changed, 127 insertions(+), 83 deletions(-) diff --git a/llvm/include/llvm/Analysis/ValueTracking.h b/llvm/include/llvm/Analysis/ValueTracking.h index 9510739ef5ab4..178f61563cd7f 100644 --- a/llvm/include/llvm/Analysis/ValueTracking.h +++ b/llvm/include/llvm/Analysis/ValueTracking.h @@ -21,6 +21,7 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Operator.h" #include #include @@ -591,18 +592,25 @@ class Value; /// the parent of I. bool programUndefinedIfPoison(const Instruction *PoisonI); - /// Return true if I can create poison from non-poison operands. - /// For vectors, canCreatePoison returns true if there is potential poison in - /// any element of the result when vectors without poison are given as + /// canCreateUndefOrPoison returns true if Op can create undef or poison from + /// non-undef & non-poison operands. + /// For vectors, canCreateUndefOrPoison returns true if there is potential + /// poison or undef in any element of the result when vectors without + /// undef/poison poison are given as operands. + /// For example, given `Op = shl <2 x i32> %x, <0, 32>`, this function returns + /// true. If Op raises immediate UB but never creates poison or undef + /// (e.g. sdiv I, 0), canCreatePoison returns false. + /// + /// canCreatePoison returns true if Op can create poison from non-poison /// operands. - /// For example, given `I = shl <2 x i32> %x, <0, 32>`, this function returns - /// true. If I raises immediate UB but never creates poison (e.g. sdiv I, 0), - /// canCreatePoison returns false. - bool canCreatePoison(const Instruction *I); + bool canCreateUndefOrPoison(const Operator *Op); + bool canCreatePoison(const Operator *Op); /// Return true if this function can prove that V is never undef value /// or poison value. - // + /// Note that this is different from canCreateUndefOrPoison because the + /// function assumes Op's operands are not poison/undef. + /// /// If CtxI and DT are specified this method performs flow-sensitive analysis /// and returns true if it is guaranteed to be never undef or poison /// immediately before the CtxI. diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 8d7bb1805a57d..380022c10acec 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4665,31 +4665,30 @@ bool llvm::isOverflowIntrinsicNoWrap(const WithOverflowInst *WO, return llvm::any_of(GuardingBranches, AllUsesGuardedByBranch); } -bool llvm::canCreatePoison(const Instruction *I) { +static bool canCreateUndefOrPoison(const Operator *Op, bool PoisonOnly) { // See whether I has flags that may create poison - if (isa(I) && - (I->hasNoSignedWrap() || I->hasNoUnsignedWrap())) - return true; - if (isa(I) && I->isExact()) - return true; - if (auto *FP = dyn_cast(I)) { + if (const auto *OvOp = dyn_cast(Op)) { + if (OvOp->hasNoSignedWrap() || OvOp->hasNoUnsignedWrap()) + return true; + } + if (const auto *ExactOp = dyn_cast(Op)) + if (ExactOp->isExact()) + return true; + if (const auto *FP = dyn_cast(Op)) { auto FMF = FP->getFastMathFlags(); if (FMF.noNaNs() || FMF.noInfs()) return true; } - if (auto *GEP = dyn_cast(I)) - if (GEP->isInBounds()) - return true; - unsigned Opcode = I->getOpcode(); + unsigned Opcode = Op->getOpcode(); - // Check whether opcode is a poison-generating operation + // Check whether opcode is a poison/undef-generating operation switch (Opcode) { case Instruction::Shl: case Instruction::AShr: case Instruction::LShr: { // Shifts return poison if shiftwidth is larger than the bitwidth. - if (auto *C = dyn_cast(I->getOperand(1))) { + if (auto *C = dyn_cast(Op->getOperand(1))) { SmallVector ShiftAmounts; if (auto *FVTy = dyn_cast(C->getType())) { unsigned NumElts = FVTy->getNumElements(); @@ -4715,41 +4714,62 @@ bool llvm::canCreatePoison(const Instruction *I) { return true; case Instruction::Call: case Instruction::CallBr: - case Instruction::Invoke: - // Function calls can return a poison value even if args are non-poison - // values. - return true; + case Instruction::Invoke: { + const auto *CB = cast(Op); + return !CB->hasRetAttr(Attribute::NoUndef); + } case Instruction::InsertElement: case Instruction::ExtractElement: { // If index exceeds the length of the vector, it returns poison - auto *VTy = cast(I->getOperand(0)->getType()); - unsigned IdxOp = I->getOpcode() == Instruction::InsertElement ? 2 : 1; - auto *Idx = dyn_cast(I->getOperand(IdxOp)); + auto *VTy = cast(Op->getOperand(0)->getType()); + unsigned IdxOp = Op->getOpcode() == Instruction::InsertElement ? 2 : 1; + auto *Idx = dyn_cast(Op->getOperand(IdxOp)); if (!Idx || Idx->getZExtValue() >= VTy->getElementCount().Min) return true; return false; } + case Instruction::ShuffleVector: { + // shufflevector may return undef. + if (PoisonOnly) + return false; + ArrayRef Mask = isa(Op) + ? cast(Op)->getShuffleMask() + : cast(Op)->getShuffleMask(); + return any_of(Mask, [](int Elt) { return Elt == UndefMaskElem; }); + } case Instruction::FNeg: case Instruction::PHI: case Instruction::Select: case Instruction::URem: case Instruction::SRem: - case Instruction::ShuffleVector: case Instruction::ExtractValue: case Instruction::InsertValue: case Instruction::Freeze: case Instruction::ICmp: case Instruction::FCmp: - case Instruction::GetElementPtr: return false; - default: - if (isa(I)) + case Instruction::GetElementPtr: { + const auto *GEP = cast(Op); + return GEP->isInBounds(); + } + default: { + const auto *CE = dyn_cast(Op); + if (isa(Op) || (CE && CE->isCast())) return false; - else if (isa(I)) + else if (isa(Op)) return false; // Be conservative and return true. return true; } + } +} + +bool llvm::canCreateUndefOrPoison(const Operator *Op) { + return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/false); +} + +bool llvm::canCreatePoison(const Operator *Op) { + return ::canCreateUndefOrPoison(Op, /*PoisonOnly=*/true); } bool llvm::isGuaranteedNotToBeUndefOrPoison(const Value *V, diff --git a/llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp b/llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp index 85e096112fca1..fa97a194ea2b5 100644 --- a/llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp +++ b/llvm/lib/Transforms/Instrumentation/PoisonChecking.cpp @@ -297,7 +297,7 @@ static bool rewrite(Function &F) { for (Value *V : I.operands()) Checks.push_back(getPoisonFor(ValToPoison, V)); - if (canCreatePoison(&I)) + if (canCreatePoison(cast(&I))) generateCreationChecks(I, Checks); ValToPoison[&I] = buildOrChain(B, Checks); } diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index 7dcb6204ba40f..a5d6df9818185 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -722,61 +722,71 @@ TEST(ValueTracking, propagatesPoison) { } } -TEST(ValueTracking, canCreatePoison) { +TEST(ValueTracking, canCreatePoisonOrUndef) { std::string AsmHead = "declare i32 @g(i32)\n" "define void @f(i32 %x, i32 %y, float %fx, float %fy, i1 %cond, " "<4 x i32> %vx, <4 x i32> %vx2, %svx, i8* %p) {\n"; std::string AsmTail = " ret void\n}"; - // (can create poison?, IR instruction) - SmallVector, 32> Data = { - {false, "add i32 %x, %y"}, - {true, "add nsw nuw i32 %x, %y"}, - {true, "shl i32 %x, %y"}, - {true, "shl <4 x i32> %vx, %vx2"}, - {true, "shl nsw i32 %x, %y"}, - {true, "shl nsw <4 x i32> %vx, "}, - {false, "shl i32 %x, 31"}, - {true, "shl i32 %x, 32"}, - {false, "shl <4 x i32> %vx, "}, - {true, "shl <4 x i32> %vx, "}, - {true, "ashr i32 %x, %y"}, - {true, "ashr exact i32 %x, %y"}, - {false, "ashr i32 %x, 31"}, - {true, "ashr exact i32 %x, 31"}, - {false, "ashr <4 x i32> %vx, "}, - {true, "ashr <4 x i32> %vx, "}, - {true, "ashr exact <4 x i32> %vx, "}, - {true, "lshr i32 %x, %y"}, - {true, "lshr exact i32 %x, 31"}, - {false, "udiv i32 %x, %y"}, - {true, "udiv exact i32 %x, %y"}, - {false, "getelementptr i8, i8* %p, i32 %x"}, - {true, "getelementptr inbounds i8, i8* %p, i32 %x"}, - {true, "fneg nnan float %fx"}, - {false, "fneg float %fx"}, - {false, "fadd float %fx, %fy"}, - {true, "fadd nnan float %fx, %fy"}, - {false, "urem i32 %x, %y"}, - {true, "fptoui float %fx to i32"}, - {true, "fptosi float %fx to i32"}, - {false, "bitcast float %fx to i32"}, - {false, "select i1 %cond, i32 %x, i32 %y"}, - {true, "select nnan i1 %cond, float %fx, float %fy"}, - {true, "extractelement <4 x i32> %vx, i32 %x"}, - {false, "extractelement <4 x i32> %vx, i32 3"}, - {true, "extractelement %svx, i32 4"}, - {true, "insertelement <4 x i32> %vx, i32 %x, i32 %y"}, - {false, "insertelement <4 x i32> %vx, i32 %x, i32 3"}, - {true, "insertelement %svx, i32 %x, i32 4"}, - {false, "freeze i32 %x"}, - {true, "call i32 @g(i32 %x)"}, - {true, "fcmp nnan oeq float %fx, %fy"}, - {false, "fcmp oeq float %fx, %fy"}}; + // (can create poison?, can create undef?, IR instruction) + SmallVector, 32> Data = { + {false, false, "add i32 %x, %y"}, + {true, false, "add nsw nuw i32 %x, %y"}, + {true, false, "shl i32 %x, %y"}, + {true, false, "shl <4 x i32> %vx, %vx2"}, + {true, false, "shl nsw i32 %x, %y"}, + {true, false, "shl nsw <4 x i32> %vx, "}, + {false, false, "shl i32 %x, 31"}, + {true, false, "shl i32 %x, 32"}, + {false, false, "shl <4 x i32> %vx, "}, + {true, false, "shl <4 x i32> %vx, "}, + {true, false, "ashr i32 %x, %y"}, + {true, false, "ashr exact i32 %x, %y"}, + {false, false, "ashr i32 %x, 31"}, + {true, false, "ashr exact i32 %x, 31"}, + {false, false, "ashr <4 x i32> %vx, "}, + {true, false, "ashr <4 x i32> %vx, "}, + {true, false, "ashr exact <4 x i32> %vx, "}, + {true, false, "lshr i32 %x, %y"}, + {true, false, "lshr exact i32 %x, 31"}, + {false, false, "udiv i32 %x, %y"}, + {true, false, "udiv exact i32 %x, %y"}, + {false, false, "getelementptr i8, i8* %p, i32 %x"}, + {true, false, "getelementptr inbounds i8, i8* %p, i32 %x"}, + {true, false, "fneg nnan float %fx"}, + {false, false, "fneg float %fx"}, + {false, false, "fadd float %fx, %fy"}, + {true, false, "fadd nnan float %fx, %fy"}, + {false, false, "urem i32 %x, %y"}, + {true, false, "fptoui float %fx to i32"}, + {true, false, "fptosi float %fx to i32"}, + {false, false, "bitcast float %fx to i32"}, + {false, false, "select i1 %cond, i32 %x, i32 %y"}, + {true, false, "select nnan i1 %cond, float %fx, float %fy"}, + {true, false, "extractelement <4 x i32> %vx, i32 %x"}, + {false, false, "extractelement <4 x i32> %vx, i32 3"}, + {true, false, "extractelement %svx, i32 4"}, + {true, false, "insertelement <4 x i32> %vx, i32 %x, i32 %y"}, + {false, false, "insertelement <4 x i32> %vx, i32 %x, i32 3"}, + {true, false, "insertelement %svx, i32 %x, i32 4"}, + {false, false, "freeze i32 %x"}, + {false, false, + "shufflevector <4 x i32> %vx, <4 x i32> %vx2, " + "<4 x i32> "}, + {false, true, + "shufflevector <4 x i32> %vx, <4 x i32> %vx2, " + "<4 x i32> "}, + {false, true, + "shufflevector %svx, " + " %svx, undef"}, + {true, false, "call i32 @g(i32 %x)"}, + {false, false, "call noundef i32 @g(i32 %x)"}, + {true, false, "fcmp nnan oeq float %fx, %fy"}, + {false, false, "fcmp oeq float %fx, %fy"}}; std::string AssemblyStr = AsmHead; for (auto &Itm : Data) - AssemblyStr += Itm.second + "\n"; + AssemblyStr += std::get<2>(Itm) + "\n"; AssemblyStr += AsmTail; LLVMContext Context; @@ -793,8 +803,14 @@ TEST(ValueTracking, canCreatePoison) { for (auto &I : BB) { if (isa(&I)) break; - EXPECT_EQ(canCreatePoison(&I), Data[Index].first) - << "Incorrect answer at instruction " << Index << " = " << I; + bool Poison = std::get<0>(Data[Index]); + bool Undef = std::get<1>(Data[Index]); + EXPECT_EQ(canCreatePoison(cast(&I)), Poison) + << "Incorrect answer of canCreatePoison at instruction " << Index + << " = " << I; + EXPECT_EQ(canCreateUndefOrPoison(cast(&I)), Undef || Poison) + << "Incorrect answer of canCreateUndef at instruction " << Index + << " = " << I; Index++; } } From 19dd3712e5ae6278656003b0734e4d83c72abf12 Mon Sep 17 00:00:00 2001 From: Logan Smith Date: Sun, 19 Jul 2020 09:35:29 -0700 Subject: [PATCH 760/771] [llvm][NFC] Add missing 'override' --- llvm/tools/llvm-rc/ResourceScriptStmt.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/llvm/tools/llvm-rc/ResourceScriptStmt.h b/llvm/tools/llvm-rc/ResourceScriptStmt.h index 7076eca96a23d..b772732e78e69 100644 --- a/llvm/tools/llvm-rc/ResourceScriptStmt.h +++ b/llvm/tools/llvm-rc/ResourceScriptStmt.h @@ -289,7 +289,9 @@ class OptStatementsRCResource : public RCResource { : RCResource(Flags), OptStatements(std::make_unique(std::move(Stmts))) {} - virtual Error applyStmts(Visitor *V) const { return OptStatements->visit(V); } + Error applyStmts(Visitor *V) const override { + return OptStatements->visit(V); + } }; // LANGUAGE statement. It can occur both as a top-level statement (in such From 6187eeb683d8c639282d437e6af585e9b7f9c93e Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Sun, 19 Jul 2020 17:24:57 +0100 Subject: [PATCH 761/771] [llvm-reduce] Fix incorrect indices in argument reduction pass The function extractArgumentsFromModule() was passing a one-based index to, but replaceFunctionCalls() was expecting a zero-based argument index. This resulted in assertion errors when reducing function call arguments with different types. Additionally, the Reviewed By: lebedev.ri Differential Revision: https://reviews.llvm.org/D84099 --- llvm/test/Reduce/remove-args-2.ll | 20 +++++++++++++++++++ .../llvm-reduce/deltas/ReduceArguments.cpp | 7 +++---- 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 llvm/test/Reduce/remove-args-2.ll diff --git a/llvm/test/Reduce/remove-args-2.ll b/llvm/test/Reduce/remove-args-2.ll new file mode 100644 index 0000000000000..fddcfc75195cf --- /dev/null +++ b/llvm/test/Reduce/remove-args-2.ll @@ -0,0 +1,20 @@ +; Test that llvm-reduce can remove uninteresting function arguments from function definitions as well as their calls. +; This test checks that functions with different argument types are handled correctly +; +; RUN: llvm-reduce --test %python --test-arg %p/Inputs/remove-args.py %s -o %t +; RUN: cat %t | FileCheck -implicit-check-not=uninteresting %s + +%struct.foo = type { %struct.foo*, i32, i32, i8* } + +define dso_local void @bar() { +entry: + ; CHECK: call void @interesting(%struct.foo* null) + call void @interesting(i32 0, i8* null, %struct.foo* null, i8* null, i64 0) + ret void +} + +; CHECK: define internal void @interesting(%struct.foo* %interesting) { +define internal void @interesting(i32 %uninteresting1, i8* %uninteresting2, %struct.foo* %interesting, i8* %uninteresting3, i64 %uninteresting4) { +entry: + ret void +} diff --git a/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp b/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp index a119b40018b34..88c3e326ff97d 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp @@ -81,10 +81,9 @@ static void extractArgumentsFromModule(std::vector ChunksToKeep, continue; std::set ArgIndexesToKeep; - int ArgI = 0; - for (auto &Arg : F->args()) - if (ArgsToKeep.count(&Arg)) - ArgIndexesToKeep.insert(++ArgI); + for (auto &Arg : enumerate(F->args())) + if (ArgsToKeep.count(&Arg.value())) + ArgIndexesToKeep.insert(Arg.index()); auto *ClonedFunc = CloneFunction(F, VMap); // In order to preserve function order, we move Clone after old Function From 8b354cc8db413f596c95b4f3240fabaa3e2c931e Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 15 Jul 2020 09:17:42 -0400 Subject: [PATCH 762/771] [ConstantFolding] check applicability of AllOnes constant creation first The getAllOnesValue can only handle things that are bitcast from a ConstantInt, while here we bitcast through a pointer, so we may see more complex objects (like Array or Struct). Differential Revision: https://reviews.llvm.org/D83870 --- llvm/lib/Analysis/ConstantFolding.cpp | 8 +++- llvm/test/Analysis/ConstantFolding/allones.ll | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 llvm/test/Analysis/ConstantFolding/allones.ll diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 8c66decaaf58d..6feffcbb98e1f 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -342,8 +342,12 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, // pointers legally). if (C->isNullValue() && !DestTy->isX86_MMXTy()) return Constant::getNullValue(DestTy); - if (C->isAllOnesValue() && !DestTy->isX86_MMXTy() && - !DestTy->isPtrOrPtrVectorTy()) // Don't get ones for ptr types! + if (C->isAllOnesValue() && + (DestTy->isIntegerTy() || DestTy->isFloatingPointTy() || + DestTy->isVectorTy()) && + !DestTy->isX86_MMXTy() && !DestTy->isPtrOrPtrVectorTy()) + // Get ones when the input is trivial, but + // only for supported types inside getAllOnesValue. return Constant::getAllOnesValue(DestTy); // If the type sizes are the same and a cast is legal, just directly diff --git a/llvm/test/Analysis/ConstantFolding/allones.ll b/llvm/test/Analysis/ConstantFolding/allones.ll new file mode 100644 index 0000000000000..1315b3628475e --- /dev/null +++ b/llvm/test/Analysis/ConstantFolding/allones.ll @@ -0,0 +1,46 @@ +; RUN: opt -early-cse -S -o - %s | FileCheck %s +target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64-ni:2" +target triple = "armv7-unknown-linux-gnueabi" + +%struct.anon = type { i32 } + +@onesstruct = private constant %struct.anon { i32 -1 }, align 4 + +define i32 @allones_struct() { +; CHECK-LABEL: @allones_struct() +; CHECK-NEXT: %1 = load [1 x i32], [1 x i32]* bitcast (%struct.anon* @onesstruct to [1 x i32]*), align 4 +; CHECK-NEXT: %2 = extractvalue [1 x i32] %1, 0 +; CHECK-NEXT: ret i32 %2 + %1 = load [1 x i32], [1 x i32]* bitcast (%struct.anon* @onesstruct to [1 x i32]*), align 4 + %2 = extractvalue [1 x i32] %1, 0 + ret i32 %2 +} + +define i32 @allones_int() { +; CHECK-LABEL: @allones_int() +; CHECK-NEXT: ret i32 -1 + %1 = load i32, i32* bitcast (%struct.anon* @onesstruct to i32*), align 4 + ret i32 %1 +} + +define i32* @allones_ptr() { +; CHECK-LABEL: @allones_ptr() +; CHECK-NEXT: ret i32* inttoptr (i32 -1 to i32*) + %1 = load i32*, i32** bitcast (%struct.anon* @onesstruct to i32**), align 4 + ret i32* %1 +} + +define i32 addrspace(1)* @allones_ptr1() { +; CHECK-LABEL: @allones_ptr1() +; CHECK-NEXT: ret i32 addrspace(1)* inttoptr (i32 -1 to i32 addrspace(1)*) + %1 = load i32 addrspace(1)*, i32 addrspace(1)** bitcast (%struct.anon* @onesstruct to i32 addrspace(1)**), align 4 + ret i32 addrspace(1)* %1 +} + +define i32 addrspace(2)* @allones_ptr2() { +; CHECK-LABEL: @allones_ptr2() +; CHECK-NEXT: %1 = load i32 addrspace(2)*, i32 addrspace(2)** bitcast (%struct.anon* @onesstruct to i32 addrspace(2)**), align 4 +; CHECK-NEXT: ret i32 addrspace(2)* %1 + %1 = load i32 addrspace(2)*, i32 addrspace(2)** bitcast (%struct.anon* @onesstruct to i32 addrspace(2)**), align 4 + ret i32 addrspace(2)* %1 +} From ef66e3d086308800d7947a385c2ae09d3f55a695 Mon Sep 17 00:00:00 2001 From: Juneyoung Lee Date: Mon, 20 Jul 2020 02:21:52 +0900 Subject: [PATCH 763/771] Fix ValueTrackingTest.cpp to use pair instead of tuple --- llvm/unittests/Analysis/ValueTrackingTest.cpp | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/llvm/unittests/Analysis/ValueTrackingTest.cpp b/llvm/unittests/Analysis/ValueTrackingTest.cpp index a5d6df9818185..75ebe9cbf8aa0 100644 --- a/llvm/unittests/Analysis/ValueTrackingTest.cpp +++ b/llvm/unittests/Analysis/ValueTrackingTest.cpp @@ -729,64 +729,64 @@ TEST(ValueTracking, canCreatePoisonOrUndef) { "<4 x i32> %vx, <4 x i32> %vx2, %svx, i8* %p) {\n"; std::string AsmTail = " ret void\n}"; // (can create poison?, can create undef?, IR instruction) - SmallVector, 32> Data = { - {false, false, "add i32 %x, %y"}, - {true, false, "add nsw nuw i32 %x, %y"}, - {true, false, "shl i32 %x, %y"}, - {true, false, "shl <4 x i32> %vx, %vx2"}, - {true, false, "shl nsw i32 %x, %y"}, - {true, false, "shl nsw <4 x i32> %vx, "}, - {false, false, "shl i32 %x, 31"}, - {true, false, "shl i32 %x, 32"}, - {false, false, "shl <4 x i32> %vx, "}, - {true, false, "shl <4 x i32> %vx, "}, - {true, false, "ashr i32 %x, %y"}, - {true, false, "ashr exact i32 %x, %y"}, - {false, false, "ashr i32 %x, 31"}, - {true, false, "ashr exact i32 %x, 31"}, - {false, false, "ashr <4 x i32> %vx, "}, - {true, false, "ashr <4 x i32> %vx, "}, - {true, false, "ashr exact <4 x i32> %vx, "}, - {true, false, "lshr i32 %x, %y"}, - {true, false, "lshr exact i32 %x, 31"}, - {false, false, "udiv i32 %x, %y"}, - {true, false, "udiv exact i32 %x, %y"}, - {false, false, "getelementptr i8, i8* %p, i32 %x"}, - {true, false, "getelementptr inbounds i8, i8* %p, i32 %x"}, - {true, false, "fneg nnan float %fx"}, - {false, false, "fneg float %fx"}, - {false, false, "fadd float %fx, %fy"}, - {true, false, "fadd nnan float %fx, %fy"}, - {false, false, "urem i32 %x, %y"}, - {true, false, "fptoui float %fx to i32"}, - {true, false, "fptosi float %fx to i32"}, - {false, false, "bitcast float %fx to i32"}, - {false, false, "select i1 %cond, i32 %x, i32 %y"}, - {true, false, "select nnan i1 %cond, float %fx, float %fy"}, - {true, false, "extractelement <4 x i32> %vx, i32 %x"}, - {false, false, "extractelement <4 x i32> %vx, i32 3"}, - {true, false, "extractelement %svx, i32 4"}, - {true, false, "insertelement <4 x i32> %vx, i32 %x, i32 %y"}, - {false, false, "insertelement <4 x i32> %vx, i32 %x, i32 3"}, - {true, false, "insertelement %svx, i32 %x, i32 4"}, - {false, false, "freeze i32 %x"}, - {false, false, + SmallVector, std::string>, 32> Data = { + {{false, false}, "add i32 %x, %y"}, + {{true, false}, "add nsw nuw i32 %x, %y"}, + {{true, false}, "shl i32 %x, %y"}, + {{true, false}, "shl <4 x i32> %vx, %vx2"}, + {{true, false}, "shl nsw i32 %x, %y"}, + {{true, false}, "shl nsw <4 x i32> %vx, "}, + {{false, false}, "shl i32 %x, 31"}, + {{true, false}, "shl i32 %x, 32"}, + {{false, false}, "shl <4 x i32> %vx, "}, + {{true, false}, "shl <4 x i32> %vx, "}, + {{true, false}, "ashr i32 %x, %y"}, + {{true, false}, "ashr exact i32 %x, %y"}, + {{false, false}, "ashr i32 %x, 31"}, + {{true, false}, "ashr exact i32 %x, 31"}, + {{false, false}, "ashr <4 x i32> %vx, "}, + {{true, false}, "ashr <4 x i32> %vx, "}, + {{true, false}, "ashr exact <4 x i32> %vx, "}, + {{true, false}, "lshr i32 %x, %y"}, + {{true, false}, "lshr exact i32 %x, 31"}, + {{false, false}, "udiv i32 %x, %y"}, + {{true, false}, "udiv exact i32 %x, %y"}, + {{false, false}, "getelementptr i8, i8* %p, i32 %x"}, + {{true, false}, "getelementptr inbounds i8, i8* %p, i32 %x"}, + {{true, false}, "fneg nnan float %fx"}, + {{false, false}, "fneg float %fx"}, + {{false, false}, "fadd float %fx, %fy"}, + {{true, false}, "fadd nnan float %fx, %fy"}, + {{false, false}, "urem i32 %x, %y"}, + {{true, false}, "fptoui float %fx to i32"}, + {{true, false}, "fptosi float %fx to i32"}, + {{false, false}, "bitcast float %fx to i32"}, + {{false, false}, "select i1 %cond, i32 %x, i32 %y"}, + {{true, false}, "select nnan i1 %cond, float %fx, float %fy"}, + {{true, false}, "extractelement <4 x i32> %vx, i32 %x"}, + {{false, false}, "extractelement <4 x i32> %vx, i32 3"}, + {{true, false}, "extractelement %svx, i32 4"}, + {{true, false}, "insertelement <4 x i32> %vx, i32 %x, i32 %y"}, + {{false, false}, "insertelement <4 x i32> %vx, i32 %x, i32 3"}, + {{true, false}, "insertelement %svx, i32 %x, i32 4"}, + {{false, false}, "freeze i32 %x"}, + {{false, false}, "shufflevector <4 x i32> %vx, <4 x i32> %vx2, " "<4 x i32> "}, - {false, true, + {{false, true}, "shufflevector <4 x i32> %vx, <4 x i32> %vx2, " "<4 x i32> "}, - {false, true, + {{false, true}, "shufflevector %svx, " " %svx, undef"}, - {true, false, "call i32 @g(i32 %x)"}, - {false, false, "call noundef i32 @g(i32 %x)"}, - {true, false, "fcmp nnan oeq float %fx, %fy"}, - {false, false, "fcmp oeq float %fx, %fy"}}; + {{true, false}, "call i32 @g(i32 %x)"}, + {{false, false}, "call noundef i32 @g(i32 %x)"}, + {{true, false}, "fcmp nnan oeq float %fx, %fy"}, + {{false, false}, "fcmp oeq float %fx, %fy"}}; std::string AssemblyStr = AsmHead; for (auto &Itm : Data) - AssemblyStr += std::get<2>(Itm) + "\n"; + AssemblyStr += Itm.second + "\n"; AssemblyStr += AsmTail; LLVMContext Context; @@ -803,8 +803,8 @@ TEST(ValueTracking, canCreatePoisonOrUndef) { for (auto &I : BB) { if (isa(&I)) break; - bool Poison = std::get<0>(Data[Index]); - bool Undef = std::get<1>(Data[Index]); + bool Poison = Data[Index].first.first; + bool Undef = Data[Index].first.second; EXPECT_EQ(canCreatePoison(cast(&I)), Poison) << "Incorrect answer of canCreatePoison at instruction " << Index << " = " << I; From f7a571537a14da83e5701864471b99b61cdcca54 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Sat, 18 Jul 2020 20:43:13 -0700 Subject: [PATCH 764/771] [JITLink][MachO] Fix handling of non-extern UNSIGNED pair of SUBTRACTOR relocs. When processing a MachO SUBTRACTOR/UNSIGNED pair, if the UNSIGNED target is non-extern then check the r_symbolnum field of the relocation to find the targeted section and use the section's address to find 'ToSymbol'. Previously 'ToSymbol' was found by loading the initial value stored at the fixup location and treating this as an address to search for. This is incorrect, however: the initial value includes the addend and will point to the wrong block if the addend is less than zero or greater than the block size. rdar://65756694 --- llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp | 9 +++++---- llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp | 9 +++++---- .../JITLink/X86/MachO_x86-64_relocations.s | 8 ++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp index 463845a5b8cbd..28adf9b3fb718 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp @@ -148,10 +148,11 @@ class MachOLinkGraphBuilder_arm64 : public MachOLinkGraphBuilder { else return ToSymbolOrErr.takeError(); } else { - if (auto ToSymbolOrErr = findSymbolByAddress(FixupValue)) - ToSymbol = &*ToSymbolOrErr; - else - return ToSymbolOrErr.takeError(); + auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1); + if (!ToSymbolSec) + return ToSymbolSec.takeError(); + ToSymbol = getSymbolByAddress(ToSymbolSec->Address); + assert(ToSymbol && "No symbol for section"); FixupValue -= ToSymbol->getAddress(); } diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp index a91bc3b6033cf..54d725eac144a 100644 --- a/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp +++ b/llvm/lib/ExecutionEngine/JITLink/MachO_x86_64.cpp @@ -150,10 +150,11 @@ class MachOLinkGraphBuilder_x86_64 : public MachOLinkGraphBuilder { else return ToSymbolOrErr.takeError(); } else { - if (auto ToSymbolOrErr = findSymbolByAddress(FixupValue)) - ToSymbol = &*ToSymbolOrErr; - else - return ToSymbolOrErr.takeError(); + auto ToSymbolSec = findSectionByIndex(UnsignedRI.r_symbolnum - 1); + if (!ToSymbolSec) + return ToSymbolSec.takeError(); + ToSymbol = getSymbolByAddress(ToSymbolSec->Address); + assert(ToSymbol && "No symbol for section"); FixupValue -= ToSymbol->getAddress(); } diff --git a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s index 6d9c26484f8fd..dd3cc455bd349 100644 --- a/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s +++ b/llvm/test/ExecutionEngine/JITLink/X86/MachO_x86-64_relocations.s @@ -193,19 +193,19 @@ anon_func_addr_quad: # X86_64_RELOC_SUBTRACTOR Quad/Long in named storage with anonymous minuend # -# jitlink-check: *{8}anon_minuend_quad1 = section_addr(macho_reloc.o, __data) - anon_minuend_quad1 + 2 +# jitlink-check: *{8}anon_minuend_quad1 = section_addr(macho_reloc.o, __data) - anon_minuend_quad1 - 2 # Only the form "B: .quad LA - B + C" is tested. The form "B: .quad B - LA + C" is # invalid because the subtrahend can not be local. .globl anon_minuend_quad1 .p2align 3 anon_minuend_quad1: - .quad Lanon_data - anon_minuend_quad1 + 2 + .quad Lanon_data - anon_minuend_quad1 - 2 -# jitlink-check: *{4}anon_minuend_long1 = (section_addr(macho_reloc.o, __data) - anon_minuend_long1 + 2)[31:0] +# jitlink-check: *{4}anon_minuend_long1 = (section_addr(macho_reloc.o, __data) - anon_minuend_long1 - 2)[31:0] .globl anon_minuend_long1 .p2align 2 anon_minuend_long1: - .long Lanon_data - anon_minuend_long1 + 2 + .long Lanon_data - anon_minuend_long1 - 2 # Check X86_64_RELOC_SUBTRACTOR Quad/Long in named storage with minuend and subtrahend. # Both forms "A: .quad A - B + C" and "A: .quad B - A + C" are tested. From fcc607a0849acafad7c655cd6932422027b99c79 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Fri, 10 Jul 2020 10:49:14 +0100 Subject: [PATCH 765/771] Move SPIRVMap initializations out of OCLUtil.h The map initialization unnecessarily ends up in almost every translation unit due to transitive inclusion. --- llvm-spirv/lib/SPIRV/OCLUtil.cpp | 537 +++++++++++++++++++++++++++++++ llvm-spirv/lib/SPIRV/OCLUtil.h | 525 ------------------------------ 2 files changed, 537 insertions(+), 525 deletions(-) diff --git a/llvm-spirv/lib/SPIRV/OCLUtil.cpp b/llvm-spirv/lib/SPIRV/OCLUtil.cpp index eff0cda426198..cb230ce01f528 100644 --- a/llvm-spirv/lib/SPIRV/OCLUtil.cpp +++ b/llvm-spirv/lib/SPIRV/OCLUtil.cpp @@ -96,11 +96,548 @@ namespace OCLUtil { #define SPIRV_IMAGE_ADDR_SPACE SPIRAS_Global #endif +} // namespace OCLUtil + +/////////////////////////////////////////////////////////////////////////////// +// +// Map definitions +// +/////////////////////////////////////////////////////////////////////////////// + +using namespace OCLUtil; +namespace SPIRV { + +template <> void SPIRVMap::init() { + add(OCLMF_Local, MemorySemanticsWorkgroupMemoryMask); + add(OCLMF_Global, MemorySemanticsCrossWorkgroupMemoryMask); + add(OCLMF_Image, MemorySemanticsImageMemoryMask); +} + +template <> +void SPIRVMap::init() { + add(OCLMFEx_Local, MemorySemanticsWorkgroupMemoryMask); + add(OCLMFEx_Global, MemorySemanticsCrossWorkgroupMemoryMask); + add(OCLMFEx_Local_Global, MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsCrossWorkgroupMemoryMask); + add(OCLMFEx_Image, MemorySemanticsImageMemoryMask); + add(OCLMFEx_Image_Local, + MemorySemanticsWorkgroupMemoryMask | MemorySemanticsImageMemoryMask); + add(OCLMFEx_Image_Global, + MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsImageMemoryMask); + add(OCLMFEx_Image_Local_Global, MemorySemanticsWorkgroupMemoryMask | + MemorySemanticsCrossWorkgroupMemoryMask | + MemorySemanticsImageMemoryMask); +} + +template <> +void SPIRVMap::init() { + add(OCLMO_relaxed, MemorySemanticsMaskNone); + add(OCLMO_acquire, MemorySemanticsAcquireMask); + add(OCLMO_release, MemorySemanticsReleaseMask); + add(OCLMO_acq_rel, MemorySemanticsAcquireReleaseMask); + add(OCLMO_seq_cst, MemorySemanticsSequentiallyConsistentMask); +} + +template <> void SPIRVMap::init() { + add(OCLMS_work_item, ScopeInvocation); + add(OCLMS_work_group, ScopeWorkgroup); + add(OCLMS_device, ScopeDevice); + add(OCLMS_all_svm_devices, ScopeCrossDevice); + add(OCLMS_sub_group, ScopeSubgroup); +} + +template <> void SPIRVMap::init() { + add("reduce", GroupOperationReduce); + add("scan_inclusive", GroupOperationInclusiveScan); + add("scan_exclusive", GroupOperationExclusiveScan); + add("ballot_bit_count", GroupOperationReduce); + add("ballot_inclusive_scan", GroupOperationInclusiveScan); + add("ballot_exclusive_scan", GroupOperationExclusiveScan); + add("non_uniform_reduce", GroupOperationReduce); + add("non_uniform_scan_inclusive", GroupOperationInclusiveScan); + add("non_uniform_scan_exclusive", GroupOperationExclusiveScan); + add("non_uniform_reduce_logical", GroupOperationReduce); + add("non_uniform_scan_inclusive_logical", GroupOperationInclusiveScan); + add("non_uniform_scan_exclusive_logical", GroupOperationExclusiveScan); + add("clustered_reduce", GroupOperationClusteredReduce); +} + +template <> void SPIRVMap::init() { + add("rte", FPRoundingModeRTE); + add("rtz", FPRoundingModeRTZ); + add("rtp", FPRoundingModeRTP); + add("rtn", FPRoundingModeRTN); +} + +template <> void SPIRVMap::init() { +#define _SPIRV_OP(x) add(OclExt::x, #x); + _SPIRV_OP(cl_images) + _SPIRV_OP(cl_doubles) + _SPIRV_OP(cl_khr_int64_base_atomics) + _SPIRV_OP(cl_khr_int64_extended_atomics) + _SPIRV_OP(cl_khr_fp16) + _SPIRV_OP(cl_khr_gl_sharing) + _SPIRV_OP(cl_khr_gl_event) + _SPIRV_OP(cl_khr_d3d10_sharing) + _SPIRV_OP(cl_khr_media_sharing) + _SPIRV_OP(cl_khr_d3d11_sharing) + _SPIRV_OP(cl_khr_global_int32_base_atomics) + _SPIRV_OP(cl_khr_global_int32_extended_atomics) + _SPIRV_OP(cl_khr_local_int32_base_atomics) + _SPIRV_OP(cl_khr_local_int32_extended_atomics) + _SPIRV_OP(cl_khr_byte_addressable_store) + _SPIRV_OP(cl_khr_3d_image_writes) + _SPIRV_OP(cl_khr_gl_msaa_sharing) + _SPIRV_OP(cl_khr_depth_images) + _SPIRV_OP(cl_khr_gl_depth_images) + _SPIRV_OP(cl_khr_subgroups) + _SPIRV_OP(cl_khr_mipmap_image) + _SPIRV_OP(cl_khr_mipmap_image_writes) + _SPIRV_OP(cl_khr_egl_event) + _SPIRV_OP(cl_khr_srgb_image_writes) +#undef _SPIRV_OP +} + +template <> void SPIRVMap::init() { + add(OclExt::cl_images, CapabilityImageBasic); + add(OclExt::cl_doubles, CapabilityFloat64); + add(OclExt::cl_khr_int64_base_atomics, CapabilityInt64Atomics); + add(OclExt::cl_khr_int64_extended_atomics, CapabilityInt64Atomics); + add(OclExt::cl_khr_fp16, CapabilityFloat16); + add(OclExt::cl_khr_subgroups, CapabilityGroups); + add(OclExt::cl_khr_mipmap_image, CapabilityImageMipmap); + add(OclExt::cl_khr_mipmap_image_writes, CapabilityImageMipmap); +} + +/// Map OpenCL work functions to SPIR-V builtin variables. +template <> void SPIRVMap::init() { + add("get_work_dim", BuiltInWorkDim); + add("get_global_size", BuiltInGlobalSize); + add("get_global_id", BuiltInGlobalInvocationId); + add("get_global_offset", BuiltInGlobalOffset); + add("get_local_size", BuiltInWorkgroupSize); + add("get_enqueued_local_size", BuiltInEnqueuedWorkgroupSize); + add("get_local_id", BuiltInLocalInvocationId); + add("get_num_groups", BuiltInNumWorkgroups); + add("get_group_id", BuiltInWorkgroupId); + add("get_global_linear_id", BuiltInGlobalLinearId); + add("get_local_linear_id", BuiltInLocalInvocationIndex); + // cl_khr_subgroups + add("get_sub_group_size", BuiltInSubgroupSize); + add("get_max_sub_group_size", BuiltInSubgroupMaxSize); + add("get_num_sub_groups", BuiltInNumSubgroups); + add("get_enqueued_num_sub_groups", BuiltInNumEnqueuedSubgroups); + add("get_sub_group_id", BuiltInSubgroupId); + add("get_sub_group_local_id", BuiltInSubgroupLocalInvocationId); + // cl_khr_subgroup_ballot + add("get_sub_group_eq_mask", BuiltInSubgroupEqMask); + add("get_sub_group_ge_mask", BuiltInSubgroupGeMask); + add("get_sub_group_gt_mask", BuiltInSubgroupGtMask); + add("get_sub_group_le_mask", BuiltInSubgroupLeMask); + add("get_sub_group_lt_mask", BuiltInSubgroupLtMask); +} + +// Maps uniqued OCL builtin function name to SPIR-V op code. +// A uniqued OCL builtin function name may be different from the real +// OCL builtin function name. e.g. instead of atomic_min, atomic_umin +// is used for atomic_min with unsigned integer parameter. +// work_group_ and sub_group_ functions are unified as group_ functions +// except work_group_barrier. +class SPIRVInstruction; +template <> void SPIRVMap::init() { +#define _SPIRV_OP(x, y) add("atom_" #x, OpAtomic##y); + // cl_khr_int64_base_atomics builtins + _SPIRV_OP(add, IAdd) + _SPIRV_OP(sub, ISub) + _SPIRV_OP(xchg, Exchange) + _SPIRV_OP(dec, IDecrement) + _SPIRV_OP(inc, IIncrement) + _SPIRV_OP(cmpxchg, CompareExchange) + // cl_khr_int64_extended_atomics builtins + _SPIRV_OP(min, SMin) + _SPIRV_OP(max, SMax) + _SPIRV_OP(and, And) + _SPIRV_OP(or, Or) + _SPIRV_OP(xor, Xor) +#undef _SPIRV_OP +#define _SPIRV_OP(x, y) add("atomic_" #x, Op##y); + // CL 2.0 atomic builtins + _SPIRV_OP(flag_test_and_set_explicit, AtomicFlagTestAndSet) + _SPIRV_OP(flag_clear_explicit, AtomicFlagClear) + _SPIRV_OP(load_explicit, AtomicLoad) + _SPIRV_OP(store_explicit, AtomicStore) + _SPIRV_OP(exchange_explicit, AtomicExchange) + _SPIRV_OP(compare_exchange_strong_explicit, AtomicCompareExchange) + _SPIRV_OP(compare_exchange_weak_explicit, AtomicCompareExchangeWeak) + _SPIRV_OP(inc, AtomicIIncrement) + _SPIRV_OP(dec, AtomicIDecrement) + _SPIRV_OP(fetch_add_explicit, AtomicIAdd) + _SPIRV_OP(fetch_sub_explicit, AtomicISub) + _SPIRV_OP(fetch_umin_explicit, AtomicUMin) + _SPIRV_OP(fetch_umax_explicit, AtomicUMax) + _SPIRV_OP(fetch_min_explicit, AtomicSMin) + _SPIRV_OP(fetch_max_explicit, AtomicSMax) + _SPIRV_OP(fetch_and_explicit, AtomicAnd) + _SPIRV_OP(fetch_or_explicit, AtomicOr) + _SPIRV_OP(fetch_xor_explicit, AtomicXor) +#undef _SPIRV_OP +#define _SPIRV_OP(x, y) add(#x, Op##y); + _SPIRV_OP(dot, Dot) + _SPIRV_OP(async_work_group_copy, GroupAsyncCopy) + _SPIRV_OP(async_work_group_strided_copy, GroupAsyncCopy) + _SPIRV_OP(wait_group_events, GroupWaitEvents) + _SPIRV_OP(isequal, FOrdEqual) + _SPIRV_OP(isnotequal, FUnordNotEqual) + _SPIRV_OP(isgreater, FOrdGreaterThan) + _SPIRV_OP(isgreaterequal, FOrdGreaterThanEqual) + _SPIRV_OP(isless, FOrdLessThan) + _SPIRV_OP(islessequal, FOrdLessThanEqual) + _SPIRV_OP(islessgreater, LessOrGreater) + _SPIRV_OP(isordered, Ordered) + _SPIRV_OP(isunordered, Unordered) + _SPIRV_OP(isfinite, IsFinite) + _SPIRV_OP(isinf, IsInf) + _SPIRV_OP(isnan, IsNan) + _SPIRV_OP(isnormal, IsNormal) + _SPIRV_OP(signbit, SignBitSet) + _SPIRV_OP(any, Any) + _SPIRV_OP(all, All) + _SPIRV_OP(popcount, BitCount) + _SPIRV_OP(get_fence, GenericPtrMemSemantics) + // CL 2.0 kernel enqueue builtins + _SPIRV_OP(enqueue_marker, EnqueueMarker) + _SPIRV_OP(enqueue_kernel, EnqueueKernel) + _SPIRV_OP(get_kernel_sub_group_count_for_ndrange_impl, + GetKernelNDrangeSubGroupCount) + _SPIRV_OP(get_kernel_max_sub_group_size_for_ndrange_impl, + GetKernelNDrangeMaxSubGroupSize) + _SPIRV_OP(get_kernel_work_group_size_impl, GetKernelWorkGroupSize) + _SPIRV_OP(get_kernel_preferred_work_group_size_multiple_impl, + GetKernelPreferredWorkGroupSizeMultiple) + _SPIRV_OP(retain_event, RetainEvent) + _SPIRV_OP(release_event, ReleaseEvent) + _SPIRV_OP(create_user_event, CreateUserEvent) + _SPIRV_OP(is_valid_event, IsValidEvent) + _SPIRV_OP(set_user_event_status, SetUserEventStatus) + _SPIRV_OP(capture_event_profiling_info, CaptureEventProfilingInfo) + _SPIRV_OP(get_default_queue, GetDefaultQueue) + _SPIRV_OP(ndrange_1D, BuildNDRange) + _SPIRV_OP(ndrange_2D, BuildNDRange) + _SPIRV_OP(ndrange_3D, BuildNDRange) + // Generic Address Space Casts + _SPIRV_OP(to_global, GenericCastToPtrExplicit) + _SPIRV_OP(to_local, GenericCastToPtrExplicit) + _SPIRV_OP(to_private, GenericCastToPtrExplicit) + // CL 2.0 pipe builtins + _SPIRV_OP(read_pipe_2, ReadPipe) + _SPIRV_OP(write_pipe_2, WritePipe) + _SPIRV_OP(read_pipe_2_bl, ReadPipeBlockingINTEL) + _SPIRV_OP(write_pipe_2_bl, WritePipeBlockingINTEL) + _SPIRV_OP(read_pipe_4, ReservedReadPipe) + _SPIRV_OP(write_pipe_4, ReservedWritePipe) + _SPIRV_OP(reserve_read_pipe, ReserveReadPipePackets) + _SPIRV_OP(reserve_write_pipe, ReserveWritePipePackets) + _SPIRV_OP(commit_read_pipe, CommitReadPipe) + _SPIRV_OP(commit_write_pipe, CommitWritePipe) + _SPIRV_OP(is_valid_reserve_id, IsValidReserveId) + _SPIRV_OP(group_reserve_read_pipe, GroupReserveReadPipePackets) + _SPIRV_OP(group_reserve_write_pipe, GroupReserveWritePipePackets) + _SPIRV_OP(group_commit_read_pipe, GroupCommitReadPipe) + _SPIRV_OP(group_commit_write_pipe, GroupCommitWritePipe) + _SPIRV_OP(get_pipe_num_packets_ro, GetNumPipePackets) + _SPIRV_OP(get_pipe_num_packets_wo, GetNumPipePackets) + _SPIRV_OP(get_pipe_max_packets_ro, GetMaxPipePackets) + _SPIRV_OP(get_pipe_max_packets_wo, GetMaxPipePackets) + // CL 2.0 workgroup builtins + _SPIRV_OP(group_all, GroupAll) + _SPIRV_OP(group_any, GroupAny) + _SPIRV_OP(group_broadcast, GroupBroadcast) + _SPIRV_OP(group_iadd, GroupIAdd) + _SPIRV_OP(group_fadd, GroupFAdd) + _SPIRV_OP(group_fmin, GroupFMin) + _SPIRV_OP(group_umin, GroupUMin) + _SPIRV_OP(group_smin, GroupSMin) + _SPIRV_OP(group_fmax, GroupFMax) + _SPIRV_OP(group_umax, GroupUMax) + _SPIRV_OP(group_smax, GroupSMax) + // CL image builtins + _SPIRV_OP(SampledImage, SampledImage) + _SPIRV_OP(ImageSampleExplicitLod, ImageSampleExplicitLod) + _SPIRV_OP(read_image, ImageRead) + _SPIRV_OP(write_image, ImageWrite) + _SPIRV_OP(get_image_channel_data_type, ImageQueryFormat) + _SPIRV_OP(get_image_channel_order, ImageQueryOrder) + _SPIRV_OP(get_image_num_mip_levels, ImageQueryLevels) + _SPIRV_OP(get_image_num_samples, ImageQuerySamples) + // Intel Subgroups builtins + _SPIRV_OP(intel_sub_group_shuffle, SubgroupShuffleINTEL) + _SPIRV_OP(intel_sub_group_shuffle_down, SubgroupShuffleDownINTEL) + _SPIRV_OP(intel_sub_group_shuffle_up, SubgroupShuffleUpINTEL) + _SPIRV_OP(intel_sub_group_shuffle_xor, SubgroupShuffleXorINTEL) + // Intel media_block_io builtins + _SPIRV_OP(intel_sub_group_media_block_read, SubgroupImageMediaBlockReadINTEL) + _SPIRV_OP(intel_sub_group_media_block_write, + SubgroupImageMediaBlockWriteINTEL) + // cl_khr_subgroup_non_uniform_vote + _SPIRV_OP(group_elect, GroupNonUniformElect) + _SPIRV_OP(group_non_uniform_all, GroupNonUniformAll) + _SPIRV_OP(group_non_uniform_any, GroupNonUniformAny) + _SPIRV_OP(group_non_uniform_all_equal, GroupNonUniformAllEqual) + // cl_khr_subgroup_ballot + _SPIRV_OP(group_non_uniform_broadcast, GroupNonUniformBroadcast) + _SPIRV_OP(group_broadcast_first, GroupNonUniformBroadcastFirst) + _SPIRV_OP(group_ballot, GroupNonUniformBallot) + _SPIRV_OP(group_inverse_ballot, GroupNonUniformInverseBallot) + _SPIRV_OP(group_ballot_bit_extract, GroupNonUniformBallotBitExtract) + _SPIRV_OP(group_ballot_bit_count_iadd, GroupNonUniformBallotBitCount) + _SPIRV_OP(group_ballot_find_lsb, GroupNonUniformBallotFindLSB) + _SPIRV_OP(group_ballot_find_msb, GroupNonUniformBallotFindMSB) + // cl_khr_subgroup_non_uniform_arithmetic + _SPIRV_OP(group_non_uniform_iadd, GroupNonUniformIAdd) + _SPIRV_OP(group_non_uniform_fadd, GroupNonUniformFAdd) + _SPIRV_OP(group_non_uniform_imul, GroupNonUniformIMul) + _SPIRV_OP(group_non_uniform_fmul, GroupNonUniformFMul) + _SPIRV_OP(group_non_uniform_smin, GroupNonUniformSMin) + _SPIRV_OP(group_non_uniform_umin, GroupNonUniformUMin) + _SPIRV_OP(group_non_uniform_fmin, GroupNonUniformFMin) + _SPIRV_OP(group_non_uniform_smax, GroupNonUniformSMax) + _SPIRV_OP(group_non_uniform_umax, GroupNonUniformUMax) + _SPIRV_OP(group_non_uniform_fmax, GroupNonUniformFMax) + _SPIRV_OP(group_non_uniform_iand, GroupNonUniformBitwiseAnd) + _SPIRV_OP(group_non_uniform_ior, GroupNonUniformBitwiseOr) + _SPIRV_OP(group_non_uniform_ixor, GroupNonUniformBitwiseXor) + _SPIRV_OP(group_non_uniform_logical_iand, GroupNonUniformLogicalAnd) + _SPIRV_OP(group_non_uniform_logical_ior, GroupNonUniformLogicalOr) + _SPIRV_OP(group_non_uniform_logical_ixor, GroupNonUniformLogicalXor) + // cl_khr_subgroup_shuffle + _SPIRV_OP(group_shuffle, GroupNonUniformShuffle) + _SPIRV_OP(group_shuffle_xor, GroupNonUniformShuffleXor) + // cl_khr_subgroup_shuffle_relative + _SPIRV_OP(group_shuffle_up, GroupNonUniformShuffleUp) + _SPIRV_OP(group_shuffle_down, GroupNonUniformShuffleDown) +#undef _SPIRV_OP +} + +template <> void SPIRVMap::init() { +#define _SPIRV_OP(x, y) add(#x, Op##y); + _SPIRV_OP(add, AtomicIAdd) + _SPIRV_OP(sub, AtomicISub) + _SPIRV_OP(xchg, AtomicExchange) + _SPIRV_OP(cmpxchg, AtomicCompareExchange) + _SPIRV_OP(inc, AtomicIIncrement) + _SPIRV_OP(dec, AtomicIDecrement) + _SPIRV_OP(min, AtomicSMin) + _SPIRV_OP(max, AtomicSMax) + _SPIRV_OP(umin, AtomicUMin) + _SPIRV_OP(umax, AtomicUMax) + _SPIRV_OP(and, AtomicAnd) + _SPIRV_OP(or, AtomicOr) + _SPIRV_OP(xor, AtomicXor) +#undef _SPIRV_OP +} + +// SPV_INTEL_device_side_avc_motion_estimation extension builtins +class SPIRVSubgroupsAVCIntelInst; +template <> void SPIRVMap::init() { + // Here is a workaround for a bug in the specification: + // 'avc' missed in 'intel_sub_group_avc' prefix. + add("intel_sub_group_ime_ref_window_size", + OpSubgroupAvcImeRefWindowSizeINTEL); + +#define _SPIRV_OP(x, y) add("intel_sub_group_avc_" #x, OpSubgroupAvc##y##INTEL); + // Initialization phase functions + _SPIRV_OP(ime_initialize, ImeInitialize) + _SPIRV_OP(fme_initialize, FmeInitialize) + _SPIRV_OP(bme_initialize, BmeInitialize) + _SPIRV_OP(sic_initialize, SicInitialize) + + // Result and payload types conversion functions + _SPIRV_OP(mce_convert_to_ime_payload, MceConvertToImePayload) + _SPIRV_OP(mce_convert_to_ime_result, MceConvertToImeResult) + _SPIRV_OP(mce_convert_to_ref_payload, MceConvertToRefPayload) + _SPIRV_OP(mce_convert_to_ref_result, MceConvertToRefResult) + _SPIRV_OP(mce_convert_to_sic_payload, MceConvertToSicPayload) + _SPIRV_OP(mce_convert_to_sic_result, MceConvertToSicResult) + _SPIRV_OP(ime_convert_to_mce_payload, ImeConvertToMcePayload) + _SPIRV_OP(ime_convert_to_mce_result, ImeConvertToMceResult) + _SPIRV_OP(ref_convert_to_mce_payload, RefConvertToMcePayload) + _SPIRV_OP(ref_convert_to_mce_result, RefConvertToMceResult) + _SPIRV_OP(sic_convert_to_mce_payload, SicConvertToMcePayload) + _SPIRV_OP(sic_convert_to_mce_result, SicConvertToMceResult) +#undef _SPIRV_OP + +// MCE instructions +#define _SPIRV_OP(x, y) \ + add("intel_sub_group_avc_mce_" #x, OpSubgroupAvcMce##y##INTEL); + _SPIRV_OP(get_default_inter_base_multi_reference_penalty, + GetDefaultInterBaseMultiReferencePenalty) + _SPIRV_OP(set_inter_base_multi_reference_penalty, + SetInterBaseMultiReferencePenalty) + _SPIRV_OP(get_default_inter_shape_penalty, GetDefaultInterShapePenalty) + _SPIRV_OP(set_inter_shape_penalty, SetInterShapePenalty) + _SPIRV_OP(get_default_inter_direction_penalty, + GetDefaultInterDirectionPenalty) + _SPIRV_OP(set_inter_direction_penalty, SetInterDirectionPenalty) + _SPIRV_OP(get_default_intra_luma_shape_penalty, + GetDefaultIntraLumaShapePenalty) + _SPIRV_OP(get_default_inter_motion_vector_cost_table, + GetDefaultInterMotionVectorCostTable) + _SPIRV_OP(get_default_high_penalty_cost_table, GetDefaultHighPenaltyCostTable) + _SPIRV_OP(get_default_medium_penalty_cost_table, + GetDefaultMediumPenaltyCostTable) + _SPIRV_OP(get_default_low_penalty_cost_table, GetDefaultLowPenaltyCostTable) + _SPIRV_OP(set_motion_vector_cost_function, SetMotionVectorCostFunction) + _SPIRV_OP(get_default_intra_luma_mode_penalty, GetDefaultIntraLumaModePenalty) + _SPIRV_OP(get_default_non_dc_luma_intra_penalty, + GetDefaultNonDcLumaIntraPenalty) + _SPIRV_OP(get_default_intra_chroma_mode_base_penalty, + GetDefaultIntraChromaModeBasePenalty) + _SPIRV_OP(set_ac_only_haar, SetAcOnlyHaar) + _SPIRV_OP(set_source_interlaced_field_polarity, + SetSourceInterlacedFieldPolarity) + _SPIRV_OP(set_single_reference_interlaced_field_polarity, + SetSingleReferenceInterlacedFieldPolarity) + _SPIRV_OP(set_dual_reference_interlaced_field_polarities, + SetDualReferenceInterlacedFieldPolarities) + _SPIRV_OP(get_motion_vectors, GetMotionVectors) + _SPIRV_OP(get_inter_distortions, GetInterDistortions) + _SPIRV_OP(get_best_inter_distortion, GetBestInterDistortions) + _SPIRV_OP(get_inter_major_shape, GetInterMajorShape) + _SPIRV_OP(get_inter_minor_shapes, GetInterMinorShape) + _SPIRV_OP(get_inter_directions, GetInterDirections) + _SPIRV_OP(get_inter_motion_vector_count, GetInterMotionVectorCount) + _SPIRV_OP(get_inter_reference_ids, GetInterReferenceIds) + _SPIRV_OP(get_inter_reference_interlaced_field_polarities, + GetInterReferenceInterlacedFieldPolarities) +#undef _SPIRV_OP + +// IME instructions +#define _SPIRV_OP(x, y) \ + add("intel_sub_group_avc_ime_" #x, OpSubgroupAvcIme##y##INTEL); + _SPIRV_OP(set_single_reference, SetSingleReference) + _SPIRV_OP(set_dual_reference, SetDualReference) + _SPIRV_OP(ref_window_size, RefWindowSize) + _SPIRV_OP(adjust_ref_offset, AdjustRefOffset) + _SPIRV_OP(set_max_motion_vector_count, SetMaxMotionVectorCount) + _SPIRV_OP(set_unidirectional_mix_disable, SetUnidirectionalMixDisable) + _SPIRV_OP(set_early_search_termination_threshold, + SetEarlySearchTerminationThreshold) + _SPIRV_OP(set_weighted_sad, SetWeightedSad) + _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) + _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) + _SPIRV_OP(evaluate_with_single_reference_streamin, + EvaluateWithSingleReferenceStreamin) + _SPIRV_OP(evaluate_with_dual_reference_streamin, + EvaluateWithDualReferenceStreamin) + _SPIRV_OP(evaluate_with_single_reference_streamout, + EvaluateWithSingleReferenceStreamout) + _SPIRV_OP(evaluate_with_dual_reference_streamout, + EvaluateWithDualReferenceStreamout) + _SPIRV_OP(evaluate_with_single_reference_streaminout, + EvaluateWithSingleReferenceStreaminout) + _SPIRV_OP(evaluate_with_dual_reference_streaminout, + EvaluateWithDualReferenceStreaminout) + _SPIRV_OP(get_single_reference_streamin, GetSingleReferenceStreamin) + _SPIRV_OP(get_dual_reference_streamin, GetDualReferenceStreamin) + _SPIRV_OP(strip_single_reference_streamout, StripSingleReferenceStreamout) + _SPIRV_OP(strip_dual_reference_streamout, StripDualReferenceStreamout) + _SPIRV_OP(get_border_reached, GetBorderReached) + _SPIRV_OP(get_truncated_search_indication, GetTruncatedSearchIndication) + _SPIRV_OP(get_unidirectional_early_search_termination, + GetUnidirectionalEarlySearchTermination) + _SPIRV_OP(get_weighting_pattern_minimum_motion_vector, + GetWeightingPatternMinimumMotionVector) + _SPIRV_OP(get_weighting_pattern_minimum_distortion, + GetWeightingPatternMinimumDistortion) +#undef _SPIRV_OP + +#define _SPIRV_OP(x, y) \ + add("intel_sub_group_avc_ime_get_streamout_major_shape_" #x, \ + OpSubgroupAvcImeGetStreamout##y##INTEL); + _SPIRV_OP(motion_vectors_single_reference, + SingleReferenceMajorShapeMotionVectors) + _SPIRV_OP(distortions_single_reference, SingleReferenceMajorShapeDistortions) + _SPIRV_OP(reference_ids_single_reference, + SingleReferenceMajorShapeReferenceIds) + _SPIRV_OP(motion_vectors_dual_reference, DualReferenceMajorShapeMotionVectors) + _SPIRV_OP(distortions_dual_reference, DualReferenceMajorShapeDistortions) + _SPIRV_OP(reference_ids_dual_reference, DualReferenceMajorShapeReferenceIds) +#undef _SPIRV_OP + +// REF instructions +#define _SPIRV_OP(x, y) \ + add("intel_sub_group_avc_ref_" #x, OpSubgroupAvcRef##y##INTEL); + _SPIRV_OP(set_bidirectional_mix_disable, SetBidirectionalMixDisable) + _SPIRV_OP(set_bilinear_filter_enable, SetBilinearFilterEnable) + _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) + _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) + _SPIRV_OP(evaluate_with_multi_reference, EvaluateWithMultiReference) + _SPIRV_OP(evaluate_with_multi_reference_interlaced, + EvaluateWithMultiReferenceInterlaced) +#undef _SPIRV_OP + +// SIC instructions +#define _SPIRV_OP(x, y) \ + add("intel_sub_group_avc_sic_" #x, OpSubgroupAvcSic##y##INTEL); + _SPIRV_OP(configure_skc, ConfigureSkc) + _SPIRV_OP(configure_ipe_luma, ConfigureIpeLuma) + _SPIRV_OP(configure_ipe_luma_chroma, ConfigureIpeLumaChroma) + _SPIRV_OP(get_motion_vector_mask, GetMotionVectorMask) + _SPIRV_OP(set_intra_luma_shape_penalty, SetIntraLumaShapePenalty) + _SPIRV_OP(set_intra_luma_mode_cost_function, SetIntraLumaModeCostFunction) + _SPIRV_OP(set_intra_chroma_mode_cost_function, SetIntraChromaModeCostFunction) + _SPIRV_OP(set_skc_bilinear_filter_enable, SetBilinearFilterEnable) + _SPIRV_OP(set_skc_forward_transform_enable, SetSkcForwardTransformEnable) + _SPIRV_OP(set_block_based_raw_skip_sad, SetBlockBasedRawSkipSad) + _SPIRV_OP(evaluate_ipe, EvaluateIpe) + _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) + _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) + _SPIRV_OP(evaluate_with_multi_reference, EvaluateWithMultiReference) + _SPIRV_OP(evaluate_with_multi_reference_interlaced, + EvaluateWithMultiReferenceInterlaced) + _SPIRV_OP(get_ipe_luma_shape, GetIpeLumaShape) + _SPIRV_OP(get_best_ipe_luma_distortion, GetBestIpeLumaDistortion) + _SPIRV_OP(get_best_ipe_chroma_distortion, GetBestIpeChromaDistortion) + _SPIRV_OP(get_packed_ipe_luma_modes, GetPackedIpeLumaModes) + _SPIRV_OP(get_ipe_chroma_mode, GetIpeChromaMode) + _SPIRV_OP(get_packed_skc_luma_count_threshold, GetPackedSkcLumaCountThreshold) + _SPIRV_OP(get_packed_skc_luma_sum_threshold, GetPackedSkcLumaSumThreshold) + _SPIRV_OP(get_inter_raw_sads, GetInterRawSads) +#undef _SPIRV_OP +} + +template <> void SPIRVMap::init() { + add("opencl.event_t", OpTypeEvent); + add("opencl.pipe_t", OpTypePipe); + add("opencl.clk_event_t", OpTypeDeviceEvent); + add("opencl.reserve_id_t", OpTypeReserveId); + add("opencl.queue_t", OpTypeQueue); + add("opencl.sampler_t", OpTypeSampler); +} + +template <> void LLVMSPIRVAtomicRmwOpCodeMap::init() { + add(llvm::AtomicRMWInst::Xchg, OpAtomicExchange); + add(llvm::AtomicRMWInst::Add, OpAtomicIAdd); + add(llvm::AtomicRMWInst::Sub, OpAtomicISub); + add(llvm::AtomicRMWInst::And, OpAtomicAnd); + add(llvm::AtomicRMWInst::Or, OpAtomicOr); + add(llvm::AtomicRMWInst::Xor, OpAtomicXor); + add(llvm::AtomicRMWInst::Max, OpAtomicSMax); + add(llvm::AtomicRMWInst::Min, OpAtomicSMin); + add(llvm::AtomicRMWInst::UMax, OpAtomicUMax); + add(llvm::AtomicRMWInst::UMin, OpAtomicUMin); +} + +} // namespace SPIRV + /////////////////////////////////////////////////////////////////////////////// // // Functions for getting builtin call info // /////////////////////////////////////////////////////////////////////////////// + +namespace OCLUtil { + AtomicWorkItemFenceLiterals getAtomicWorkItemFenceLiterals(CallInst *CI) { return std::make_tuple(getArgAsInt(CI, 0), static_cast(getArgAsInt(CI, 1)), diff --git a/llvm-spirv/lib/SPIRV/OCLUtil.h b/llvm-spirv/lib/SPIRV/OCLUtil.h index d91316e0a310f..3d4ae9b9ae2e5 100644 --- a/llvm-spirv/lib/SPIRV/OCLUtil.h +++ b/llvm-spirv/lib/SPIRV/OCLUtil.h @@ -444,52 +444,8 @@ std::string getIntelSubgroupBlockDataPostfix(unsigned ElementBitSize, unsigned VectorNumElements); } // namespace OCLUtil -/////////////////////////////////////////////////////////////////////////////// -// -// Map definitions -// -/////////////////////////////////////////////////////////////////////////////// - using namespace OCLUtil; namespace SPIRV { -template <> inline void SPIRVMap::init() { - add(OCLMF_Local, MemorySemanticsWorkgroupMemoryMask); - add(OCLMF_Global, MemorySemanticsCrossWorkgroupMemoryMask); - add(OCLMF_Image, MemorySemanticsImageMemoryMask); -} - -template <> -inline void SPIRVMap::init() { - add(OCLMFEx_Local, MemorySemanticsWorkgroupMemoryMask); - add(OCLMFEx_Global, MemorySemanticsCrossWorkgroupMemoryMask); - add(OCLMFEx_Local_Global, MemorySemanticsWorkgroupMemoryMask | - MemorySemanticsCrossWorkgroupMemoryMask); - add(OCLMFEx_Image, MemorySemanticsImageMemoryMask); - add(OCLMFEx_Image_Local, - MemorySemanticsWorkgroupMemoryMask | MemorySemanticsImageMemoryMask); - add(OCLMFEx_Image_Global, - MemorySemanticsCrossWorkgroupMemoryMask | MemorySemanticsImageMemoryMask); - add(OCLMFEx_Image_Local_Global, MemorySemanticsWorkgroupMemoryMask | - MemorySemanticsCrossWorkgroupMemoryMask | - MemorySemanticsImageMemoryMask); -} - -template <> -inline void SPIRVMap::init() { - add(OCLMO_relaxed, MemorySemanticsMaskNone); - add(OCLMO_acquire, MemorySemanticsAcquireMask); - add(OCLMO_release, MemorySemanticsReleaseMask); - add(OCLMO_acq_rel, MemorySemanticsAcquireReleaseMask); - add(OCLMO_seq_cst, MemorySemanticsSequentiallyConsistentMask); -} - -template <> inline void SPIRVMap::init() { - add(OCLMS_work_item, ScopeInvocation); - add(OCLMS_work_group, ScopeWorkgroup); - add(OCLMS_device, ScopeDevice); - add(OCLMS_all_svm_devices, ScopeCrossDevice); - add(OCLMS_sub_group, ScopeSubgroup); -} template Instruction * @@ -623,492 +579,11 @@ Value *transSPIRVMemorySemanticsIntoOCLMemoryOrder(Value *MemorySemantics, Value *transSPIRVMemorySemanticsIntoOCLMemFenceFlags(Value *MemorySemantics, Instruction *InsertBefore); -template <> inline void SPIRVMap::init() { - add("reduce", GroupOperationReduce); - add("scan_inclusive", GroupOperationInclusiveScan); - add("scan_exclusive", GroupOperationExclusiveScan); - add("ballot_bit_count", GroupOperationReduce); - add("ballot_inclusive_scan", GroupOperationInclusiveScan); - add("ballot_exclusive_scan", GroupOperationExclusiveScan); - add("non_uniform_reduce", GroupOperationReduce); - add("non_uniform_scan_inclusive", GroupOperationInclusiveScan); - add("non_uniform_scan_exclusive", GroupOperationExclusiveScan); - add("non_uniform_reduce_logical", GroupOperationReduce); - add("non_uniform_scan_inclusive_logical", GroupOperationInclusiveScan); - add("non_uniform_scan_exclusive_logical", GroupOperationExclusiveScan); - add("clustered_reduce", GroupOperationClusteredReduce); -} - -template <> inline void SPIRVMap::init() { - add("rte", FPRoundingModeRTE); - add("rtz", FPRoundingModeRTZ); - add("rtp", FPRoundingModeRTP); - add("rtn", FPRoundingModeRTN); -} - -template <> inline void SPIRVMap::init() { -#define _SPIRV_OP(x) add(OclExt::x, #x); - _SPIRV_OP(cl_images) - _SPIRV_OP(cl_doubles) - _SPIRV_OP(cl_khr_int64_base_atomics) - _SPIRV_OP(cl_khr_int64_extended_atomics) - _SPIRV_OP(cl_khr_fp16) - _SPIRV_OP(cl_khr_gl_sharing) - _SPIRV_OP(cl_khr_gl_event) - _SPIRV_OP(cl_khr_d3d10_sharing) - _SPIRV_OP(cl_khr_media_sharing) - _SPIRV_OP(cl_khr_d3d11_sharing) - _SPIRV_OP(cl_khr_global_int32_base_atomics) - _SPIRV_OP(cl_khr_global_int32_extended_atomics) - _SPIRV_OP(cl_khr_local_int32_base_atomics) - _SPIRV_OP(cl_khr_local_int32_extended_atomics) - _SPIRV_OP(cl_khr_byte_addressable_store) - _SPIRV_OP(cl_khr_3d_image_writes) - _SPIRV_OP(cl_khr_gl_msaa_sharing) - _SPIRV_OP(cl_khr_depth_images) - _SPIRV_OP(cl_khr_gl_depth_images) - _SPIRV_OP(cl_khr_subgroups) - _SPIRV_OP(cl_khr_mipmap_image) - _SPIRV_OP(cl_khr_mipmap_image_writes) - _SPIRV_OP(cl_khr_egl_event) - _SPIRV_OP(cl_khr_srgb_image_writes) -#undef _SPIRV_OP -} - -template <> inline void SPIRVMap::init() { - add(OclExt::cl_images, CapabilityImageBasic); - add(OclExt::cl_doubles, CapabilityFloat64); - add(OclExt::cl_khr_int64_base_atomics, CapabilityInt64Atomics); - add(OclExt::cl_khr_int64_extended_atomics, CapabilityInt64Atomics); - add(OclExt::cl_khr_fp16, CapabilityFloat16); - add(OclExt::cl_khr_subgroups, CapabilityGroups); - add(OclExt::cl_khr_mipmap_image, CapabilityImageMipmap); - add(OclExt::cl_khr_mipmap_image_writes, CapabilityImageMipmap); -} - -/// Map OpenCL work functions to SPIR-V builtin variables. -template <> -inline void SPIRVMap::init() { - add("get_work_dim", BuiltInWorkDim); - add("get_global_size", BuiltInGlobalSize); - add("get_global_id", BuiltInGlobalInvocationId); - add("get_global_offset", BuiltInGlobalOffset); - add("get_local_size", BuiltInWorkgroupSize); - add("get_enqueued_local_size", BuiltInEnqueuedWorkgroupSize); - add("get_local_id", BuiltInLocalInvocationId); - add("get_num_groups", BuiltInNumWorkgroups); - add("get_group_id", BuiltInWorkgroupId); - add("get_global_linear_id", BuiltInGlobalLinearId); - add("get_local_linear_id", BuiltInLocalInvocationIndex); - // cl_khr_subgroups - add("get_sub_group_size", BuiltInSubgroupSize); - add("get_max_sub_group_size", BuiltInSubgroupMaxSize); - add("get_num_sub_groups", BuiltInNumSubgroups); - add("get_enqueued_num_sub_groups", BuiltInNumEnqueuedSubgroups); - add("get_sub_group_id", BuiltInSubgroupId); - add("get_sub_group_local_id", BuiltInSubgroupLocalInvocationId); - // cl_khr_subgroup_ballot - add("get_sub_group_eq_mask", BuiltInSubgroupEqMask); - add("get_sub_group_ge_mask", BuiltInSubgroupGeMask); - add("get_sub_group_gt_mask", BuiltInSubgroupGtMask); - add("get_sub_group_le_mask", BuiltInSubgroupLeMask); - add("get_sub_group_lt_mask", BuiltInSubgroupLtMask); -} - -// Maps uniqued OCL builtin function name to SPIR-V op code. -// A uniqued OCL builtin function name may be different from the real -// OCL builtin function name. e.g. instead of atomic_min, atomic_umin -// is used for atomic_min with unsigned integer parameter. -// work_group_ and sub_group_ functions are unified as group_ functions -// except work_group_barrier. -class SPIRVInstruction; -template <> inline void SPIRVMap::init() { -#define _SPIRV_OP(x, y) add("atom_" #x, OpAtomic##y); - // cl_khr_int64_base_atomics builtins - _SPIRV_OP(add, IAdd) - _SPIRV_OP(sub, ISub) - _SPIRV_OP(xchg, Exchange) - _SPIRV_OP(dec, IDecrement) - _SPIRV_OP(inc, IIncrement) - _SPIRV_OP(cmpxchg, CompareExchange) - // cl_khr_int64_extended_atomics builtins - _SPIRV_OP(min, SMin) - _SPIRV_OP(max, SMax) - _SPIRV_OP(and, And) - _SPIRV_OP(or, Or) - _SPIRV_OP(xor, Xor) -#undef _SPIRV_OP -#define _SPIRV_OP(x, y) add("atomic_" #x, Op##y); - // CL 2.0 atomic builtins - _SPIRV_OP(flag_test_and_set_explicit, AtomicFlagTestAndSet) - _SPIRV_OP(flag_clear_explicit, AtomicFlagClear) - _SPIRV_OP(load_explicit, AtomicLoad) - _SPIRV_OP(store_explicit, AtomicStore) - _SPIRV_OP(exchange_explicit, AtomicExchange) - _SPIRV_OP(compare_exchange_strong_explicit, AtomicCompareExchange) - _SPIRV_OP(compare_exchange_weak_explicit, AtomicCompareExchangeWeak) - _SPIRV_OP(inc, AtomicIIncrement) - _SPIRV_OP(dec, AtomicIDecrement) - _SPIRV_OP(fetch_add_explicit, AtomicIAdd) - _SPIRV_OP(fetch_sub_explicit, AtomicISub) - _SPIRV_OP(fetch_umin_explicit, AtomicUMin) - _SPIRV_OP(fetch_umax_explicit, AtomicUMax) - _SPIRV_OP(fetch_min_explicit, AtomicSMin) - _SPIRV_OP(fetch_max_explicit, AtomicSMax) - _SPIRV_OP(fetch_and_explicit, AtomicAnd) - _SPIRV_OP(fetch_or_explicit, AtomicOr) - _SPIRV_OP(fetch_xor_explicit, AtomicXor) -#undef _SPIRV_OP -#define _SPIRV_OP(x, y) add(#x, Op##y); - _SPIRV_OP(dot, Dot) - _SPIRV_OP(async_work_group_copy, GroupAsyncCopy) - _SPIRV_OP(async_work_group_strided_copy, GroupAsyncCopy) - _SPIRV_OP(wait_group_events, GroupWaitEvents) - _SPIRV_OP(isequal, FOrdEqual) - _SPIRV_OP(isnotequal, FUnordNotEqual) - _SPIRV_OP(isgreater, FOrdGreaterThan) - _SPIRV_OP(isgreaterequal, FOrdGreaterThanEqual) - _SPIRV_OP(isless, FOrdLessThan) - _SPIRV_OP(islessequal, FOrdLessThanEqual) - _SPIRV_OP(islessgreater, LessOrGreater) - _SPIRV_OP(isordered, Ordered) - _SPIRV_OP(isunordered, Unordered) - _SPIRV_OP(isfinite, IsFinite) - _SPIRV_OP(isinf, IsInf) - _SPIRV_OP(isnan, IsNan) - _SPIRV_OP(isnormal, IsNormal) - _SPIRV_OP(signbit, SignBitSet) - _SPIRV_OP(any, Any) - _SPIRV_OP(all, All) - _SPIRV_OP(popcount, BitCount) - _SPIRV_OP(get_fence, GenericPtrMemSemantics) - // CL 2.0 kernel enqueue builtins - _SPIRV_OP(enqueue_marker, EnqueueMarker) - _SPIRV_OP(enqueue_kernel, EnqueueKernel) - _SPIRV_OP(get_kernel_sub_group_count_for_ndrange_impl, - GetKernelNDrangeSubGroupCount) - _SPIRV_OP(get_kernel_max_sub_group_size_for_ndrange_impl, - GetKernelNDrangeMaxSubGroupSize) - _SPIRV_OP(get_kernel_work_group_size_impl, GetKernelWorkGroupSize) - _SPIRV_OP(get_kernel_preferred_work_group_size_multiple_impl, - GetKernelPreferredWorkGroupSizeMultiple) - _SPIRV_OP(retain_event, RetainEvent) - _SPIRV_OP(release_event, ReleaseEvent) - _SPIRV_OP(create_user_event, CreateUserEvent) - _SPIRV_OP(is_valid_event, IsValidEvent) - _SPIRV_OP(set_user_event_status, SetUserEventStatus) - _SPIRV_OP(capture_event_profiling_info, CaptureEventProfilingInfo) - _SPIRV_OP(get_default_queue, GetDefaultQueue) - _SPIRV_OP(ndrange_1D, BuildNDRange) - _SPIRV_OP(ndrange_2D, BuildNDRange) - _SPIRV_OP(ndrange_3D, BuildNDRange) - // Generic Address Space Casts - _SPIRV_OP(to_global, GenericCastToPtrExplicit) - _SPIRV_OP(to_local, GenericCastToPtrExplicit) - _SPIRV_OP(to_private, GenericCastToPtrExplicit) - // CL 2.0 pipe builtins - _SPIRV_OP(read_pipe_2, ReadPipe) - _SPIRV_OP(write_pipe_2, WritePipe) - _SPIRV_OP(read_pipe_2_bl, ReadPipeBlockingINTEL) - _SPIRV_OP(write_pipe_2_bl, WritePipeBlockingINTEL) - _SPIRV_OP(read_pipe_4, ReservedReadPipe) - _SPIRV_OP(write_pipe_4, ReservedWritePipe) - _SPIRV_OP(reserve_read_pipe, ReserveReadPipePackets) - _SPIRV_OP(reserve_write_pipe, ReserveWritePipePackets) - _SPIRV_OP(commit_read_pipe, CommitReadPipe) - _SPIRV_OP(commit_write_pipe, CommitWritePipe) - _SPIRV_OP(is_valid_reserve_id, IsValidReserveId) - _SPIRV_OP(group_reserve_read_pipe, GroupReserveReadPipePackets) - _SPIRV_OP(group_reserve_write_pipe, GroupReserveWritePipePackets) - _SPIRV_OP(group_commit_read_pipe, GroupCommitReadPipe) - _SPIRV_OP(group_commit_write_pipe, GroupCommitWritePipe) - _SPIRV_OP(get_pipe_num_packets_ro, GetNumPipePackets) - _SPIRV_OP(get_pipe_num_packets_wo, GetNumPipePackets) - _SPIRV_OP(get_pipe_max_packets_ro, GetMaxPipePackets) - _SPIRV_OP(get_pipe_max_packets_wo, GetMaxPipePackets) - // CL 2.0 workgroup builtins - _SPIRV_OP(group_all, GroupAll) - _SPIRV_OP(group_any, GroupAny) - _SPIRV_OP(group_broadcast, GroupBroadcast) - _SPIRV_OP(group_iadd, GroupIAdd) - _SPIRV_OP(group_fadd, GroupFAdd) - _SPIRV_OP(group_fmin, GroupFMin) - _SPIRV_OP(group_umin, GroupUMin) - _SPIRV_OP(group_smin, GroupSMin) - _SPIRV_OP(group_fmax, GroupFMax) - _SPIRV_OP(group_umax, GroupUMax) - _SPIRV_OP(group_smax, GroupSMax) - // CL image builtins - _SPIRV_OP(SampledImage, SampledImage) - _SPIRV_OP(ImageSampleExplicitLod, ImageSampleExplicitLod) - _SPIRV_OP(read_image, ImageRead) - _SPIRV_OP(write_image, ImageWrite) - _SPIRV_OP(get_image_channel_data_type, ImageQueryFormat) - _SPIRV_OP(get_image_channel_order, ImageQueryOrder) - _SPIRV_OP(get_image_num_mip_levels, ImageQueryLevels) - _SPIRV_OP(get_image_num_samples, ImageQuerySamples) - // Intel Subgroups builtins - _SPIRV_OP(intel_sub_group_shuffle, SubgroupShuffleINTEL) - _SPIRV_OP(intel_sub_group_shuffle_down, SubgroupShuffleDownINTEL) - _SPIRV_OP(intel_sub_group_shuffle_up, SubgroupShuffleUpINTEL) - _SPIRV_OP(intel_sub_group_shuffle_xor, SubgroupShuffleXorINTEL) - // Intel media_block_io builtins - _SPIRV_OP(intel_sub_group_media_block_read, SubgroupImageMediaBlockReadINTEL) - _SPIRV_OP(intel_sub_group_media_block_write, - SubgroupImageMediaBlockWriteINTEL) - // cl_khr_subgroup_non_uniform_vote - _SPIRV_OP(group_elect, GroupNonUniformElect) - _SPIRV_OP(group_non_uniform_all, GroupNonUniformAll) - _SPIRV_OP(group_non_uniform_any, GroupNonUniformAny) - _SPIRV_OP(group_non_uniform_all_equal, GroupNonUniformAllEqual) - // cl_khr_subgroup_ballot - _SPIRV_OP(group_non_uniform_broadcast, GroupNonUniformBroadcast) - _SPIRV_OP(group_broadcast_first, GroupNonUniformBroadcastFirst) - _SPIRV_OP(group_ballot, GroupNonUniformBallot) - _SPIRV_OP(group_inverse_ballot, GroupNonUniformInverseBallot) - _SPIRV_OP(group_ballot_bit_extract, GroupNonUniformBallotBitExtract) - _SPIRV_OP(group_ballot_bit_count_iadd, GroupNonUniformBallotBitCount) - _SPIRV_OP(group_ballot_find_lsb, GroupNonUniformBallotFindLSB) - _SPIRV_OP(group_ballot_find_msb, GroupNonUniformBallotFindMSB) - // cl_khr_subgroup_non_uniform_arithmetic - _SPIRV_OP(group_non_uniform_iadd, GroupNonUniformIAdd) - _SPIRV_OP(group_non_uniform_fadd, GroupNonUniformFAdd) - _SPIRV_OP(group_non_uniform_imul, GroupNonUniformIMul) - _SPIRV_OP(group_non_uniform_fmul, GroupNonUniformFMul) - _SPIRV_OP(group_non_uniform_smin, GroupNonUniformSMin) - _SPIRV_OP(group_non_uniform_umin, GroupNonUniformUMin) - _SPIRV_OP(group_non_uniform_fmin, GroupNonUniformFMin) - _SPIRV_OP(group_non_uniform_smax, GroupNonUniformSMax) - _SPIRV_OP(group_non_uniform_umax, GroupNonUniformUMax) - _SPIRV_OP(group_non_uniform_fmax, GroupNonUniformFMax) - _SPIRV_OP(group_non_uniform_iand, GroupNonUniformBitwiseAnd) - _SPIRV_OP(group_non_uniform_ior, GroupNonUniformBitwiseOr) - _SPIRV_OP(group_non_uniform_ixor, GroupNonUniformBitwiseXor) - _SPIRV_OP(group_non_uniform_logical_iand, GroupNonUniformLogicalAnd) - _SPIRV_OP(group_non_uniform_logical_ior, GroupNonUniformLogicalOr) - _SPIRV_OP(group_non_uniform_logical_ixor, GroupNonUniformLogicalXor) - // cl_khr_subgroup_shuffle - _SPIRV_OP(group_shuffle, GroupNonUniformShuffle) - _SPIRV_OP(group_shuffle_xor, GroupNonUniformShuffleXor) - // cl_khr_subgroup_shuffle_relative - _SPIRV_OP(group_shuffle_up, GroupNonUniformShuffleUp) - _SPIRV_OP(group_shuffle_down, GroupNonUniformShuffleDown) -#undef _SPIRV_OP -} - -template <> inline void SPIRVMap::init() { -#define _SPIRV_OP(x, y) add(#x, Op##y); - _SPIRV_OP(add, AtomicIAdd) - _SPIRV_OP(sub, AtomicISub) - _SPIRV_OP(xchg, AtomicExchange) - _SPIRV_OP(cmpxchg, AtomicCompareExchange) - _SPIRV_OP(inc, AtomicIIncrement) - _SPIRV_OP(dec, AtomicIDecrement) - _SPIRV_OP(min, AtomicSMin) - _SPIRV_OP(max, AtomicSMax) - _SPIRV_OP(umin, AtomicUMin) - _SPIRV_OP(umax, AtomicUMax) - _SPIRV_OP(and, AtomicAnd) - _SPIRV_OP(or, AtomicOr) - _SPIRV_OP(xor, AtomicXor) -#undef _SPIRV_OP -} - -// SPV_INTEL_device_side_avc_motion_estimation extension builtins class SPIRVSubgroupsAVCIntelInst; -template <> -inline void SPIRVMap::init() { - // Here is a workaround for a bug in the specification: - // 'avc' missed in 'intel_sub_group_avc' prefix. - add("intel_sub_group_ime_ref_window_size", - OpSubgroupAvcImeRefWindowSizeINTEL); - -#define _SPIRV_OP(x, y) add("intel_sub_group_avc_" #x, OpSubgroupAvc##y##INTEL); - // Initialization phase functions - _SPIRV_OP(ime_initialize, ImeInitialize) - _SPIRV_OP(fme_initialize, FmeInitialize) - _SPIRV_OP(bme_initialize, BmeInitialize) - _SPIRV_OP(sic_initialize, SicInitialize) - - // Result and payload types conversion functions - _SPIRV_OP(mce_convert_to_ime_payload, MceConvertToImePayload) - _SPIRV_OP(mce_convert_to_ime_result, MceConvertToImeResult) - _SPIRV_OP(mce_convert_to_ref_payload, MceConvertToRefPayload) - _SPIRV_OP(mce_convert_to_ref_result, MceConvertToRefResult) - _SPIRV_OP(mce_convert_to_sic_payload, MceConvertToSicPayload) - _SPIRV_OP(mce_convert_to_sic_result, MceConvertToSicResult) - _SPIRV_OP(ime_convert_to_mce_payload, ImeConvertToMcePayload) - _SPIRV_OP(ime_convert_to_mce_result, ImeConvertToMceResult) - _SPIRV_OP(ref_convert_to_mce_payload, RefConvertToMcePayload) - _SPIRV_OP(ref_convert_to_mce_result, RefConvertToMceResult) - _SPIRV_OP(sic_convert_to_mce_payload, SicConvertToMcePayload) - _SPIRV_OP(sic_convert_to_mce_result, SicConvertToMceResult) -#undef _SPIRV_OP - -// MCE instructions -#define _SPIRV_OP(x, y) \ - add("intel_sub_group_avc_mce_" #x, OpSubgroupAvcMce##y##INTEL); - _SPIRV_OP(get_default_inter_base_multi_reference_penalty, - GetDefaultInterBaseMultiReferencePenalty) - _SPIRV_OP(set_inter_base_multi_reference_penalty, - SetInterBaseMultiReferencePenalty) - _SPIRV_OP(get_default_inter_shape_penalty, GetDefaultInterShapePenalty) - _SPIRV_OP(set_inter_shape_penalty, SetInterShapePenalty) - _SPIRV_OP(get_default_inter_direction_penalty, - GetDefaultInterDirectionPenalty) - _SPIRV_OP(set_inter_direction_penalty, SetInterDirectionPenalty) - _SPIRV_OP(get_default_intra_luma_shape_penalty, - GetDefaultIntraLumaShapePenalty) - _SPIRV_OP(get_default_inter_motion_vector_cost_table, - GetDefaultInterMotionVectorCostTable) - _SPIRV_OP(get_default_high_penalty_cost_table, GetDefaultHighPenaltyCostTable) - _SPIRV_OP(get_default_medium_penalty_cost_table, - GetDefaultMediumPenaltyCostTable) - _SPIRV_OP(get_default_low_penalty_cost_table, GetDefaultLowPenaltyCostTable) - _SPIRV_OP(set_motion_vector_cost_function, SetMotionVectorCostFunction) - _SPIRV_OP(get_default_intra_luma_mode_penalty, GetDefaultIntraLumaModePenalty) - _SPIRV_OP(get_default_non_dc_luma_intra_penalty, - GetDefaultNonDcLumaIntraPenalty) - _SPIRV_OP(get_default_intra_chroma_mode_base_penalty, - GetDefaultIntraChromaModeBasePenalty) - _SPIRV_OP(set_ac_only_haar, SetAcOnlyHaar) - _SPIRV_OP(set_source_interlaced_field_polarity, - SetSourceInterlacedFieldPolarity) - _SPIRV_OP(set_single_reference_interlaced_field_polarity, - SetSingleReferenceInterlacedFieldPolarity) - _SPIRV_OP(set_dual_reference_interlaced_field_polarities, - SetDualReferenceInterlacedFieldPolarities) - _SPIRV_OP(get_motion_vectors, GetMotionVectors) - _SPIRV_OP(get_inter_distortions, GetInterDistortions) - _SPIRV_OP(get_best_inter_distortion, GetBestInterDistortions) - _SPIRV_OP(get_inter_major_shape, GetInterMajorShape) - _SPIRV_OP(get_inter_minor_shapes, GetInterMinorShape) - _SPIRV_OP(get_inter_directions, GetInterDirections) - _SPIRV_OP(get_inter_motion_vector_count, GetInterMotionVectorCount) - _SPIRV_OP(get_inter_reference_ids, GetInterReferenceIds) - _SPIRV_OP(get_inter_reference_interlaced_field_polarities, - GetInterReferenceInterlacedFieldPolarities) -#undef _SPIRV_OP - -// IME instructions -#define _SPIRV_OP(x, y) \ - add("intel_sub_group_avc_ime_" #x, OpSubgroupAvcIme##y##INTEL); - _SPIRV_OP(set_single_reference, SetSingleReference) - _SPIRV_OP(set_dual_reference, SetDualReference) - _SPIRV_OP(ref_window_size, RefWindowSize) - _SPIRV_OP(adjust_ref_offset, AdjustRefOffset) - _SPIRV_OP(set_max_motion_vector_count, SetMaxMotionVectorCount) - _SPIRV_OP(set_unidirectional_mix_disable, SetUnidirectionalMixDisable) - _SPIRV_OP(set_early_search_termination_threshold, - SetEarlySearchTerminationThreshold) - _SPIRV_OP(set_weighted_sad, SetWeightedSad) - _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) - _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) - _SPIRV_OP(evaluate_with_single_reference_streamin, - EvaluateWithSingleReferenceStreamin) - _SPIRV_OP(evaluate_with_dual_reference_streamin, - EvaluateWithDualReferenceStreamin) - _SPIRV_OP(evaluate_with_single_reference_streamout, - EvaluateWithSingleReferenceStreamout) - _SPIRV_OP(evaluate_with_dual_reference_streamout, - EvaluateWithDualReferenceStreamout) - _SPIRV_OP(evaluate_with_single_reference_streaminout, - EvaluateWithSingleReferenceStreaminout) - _SPIRV_OP(evaluate_with_dual_reference_streaminout, - EvaluateWithDualReferenceStreaminout) - _SPIRV_OP(get_single_reference_streamin, GetSingleReferenceStreamin) - _SPIRV_OP(get_dual_reference_streamin, GetDualReferenceStreamin) - _SPIRV_OP(strip_single_reference_streamout, StripSingleReferenceStreamout) - _SPIRV_OP(strip_dual_reference_streamout, StripDualReferenceStreamout) - _SPIRV_OP(get_border_reached, GetBorderReached) - _SPIRV_OP(get_truncated_search_indication, GetTruncatedSearchIndication) - _SPIRV_OP(get_unidirectional_early_search_termination, - GetUnidirectionalEarlySearchTermination) - _SPIRV_OP(get_weighting_pattern_minimum_motion_vector, - GetWeightingPatternMinimumMotionVector) - _SPIRV_OP(get_weighting_pattern_minimum_distortion, - GetWeightingPatternMinimumDistortion) -#undef _SPIRV_OP - -#define _SPIRV_OP(x, y) \ - add("intel_sub_group_avc_ime_get_streamout_major_shape_" #x, \ - OpSubgroupAvcImeGetStreamout##y##INTEL); - _SPIRV_OP(motion_vectors_single_reference, - SingleReferenceMajorShapeMotionVectors) - _SPIRV_OP(distortions_single_reference, SingleReferenceMajorShapeDistortions) - _SPIRV_OP(reference_ids_single_reference, - SingleReferenceMajorShapeReferenceIds) - _SPIRV_OP(motion_vectors_dual_reference, DualReferenceMajorShapeMotionVectors) - _SPIRV_OP(distortions_dual_reference, DualReferenceMajorShapeDistortions) - _SPIRV_OP(reference_ids_dual_reference, DualReferenceMajorShapeReferenceIds) -#undef _SPIRV_OP - -// REF instructions -#define _SPIRV_OP(x, y) \ - add("intel_sub_group_avc_ref_" #x, OpSubgroupAvcRef##y##INTEL); - _SPIRV_OP(set_bidirectional_mix_disable, SetBidirectionalMixDisable) - _SPIRV_OP(set_bilinear_filter_enable, SetBilinearFilterEnable) - _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) - _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) - _SPIRV_OP(evaluate_with_multi_reference, EvaluateWithMultiReference) - _SPIRV_OP(evaluate_with_multi_reference_interlaced, - EvaluateWithMultiReferenceInterlaced) -#undef _SPIRV_OP - -// SIC instructions -#define _SPIRV_OP(x, y) \ - add("intel_sub_group_avc_sic_" #x, OpSubgroupAvcSic##y##INTEL); - _SPIRV_OP(configure_skc, ConfigureSkc) - _SPIRV_OP(configure_ipe_luma, ConfigureIpeLuma) - _SPIRV_OP(configure_ipe_luma_chroma, ConfigureIpeLumaChroma) - _SPIRV_OP(get_motion_vector_mask, GetMotionVectorMask) - _SPIRV_OP(set_intra_luma_shape_penalty, SetIntraLumaShapePenalty) - _SPIRV_OP(set_intra_luma_mode_cost_function, SetIntraLumaModeCostFunction) - _SPIRV_OP(set_intra_chroma_mode_cost_function, SetIntraChromaModeCostFunction) - _SPIRV_OP(set_skc_bilinear_filter_enable, SetBilinearFilterEnable) - _SPIRV_OP(set_skc_forward_transform_enable, SetSkcForwardTransformEnable) - _SPIRV_OP(set_block_based_raw_skip_sad, SetBlockBasedRawSkipSad) - _SPIRV_OP(evaluate_ipe, EvaluateIpe) - _SPIRV_OP(evaluate_with_single_reference, EvaluateWithSingleReference) - _SPIRV_OP(evaluate_with_dual_reference, EvaluateWithDualReference) - _SPIRV_OP(evaluate_with_multi_reference, EvaluateWithMultiReference) - _SPIRV_OP(evaluate_with_multi_reference_interlaced, - EvaluateWithMultiReferenceInterlaced) - _SPIRV_OP(get_ipe_luma_shape, GetIpeLumaShape) - _SPIRV_OP(get_best_ipe_luma_distortion, GetBestIpeLumaDistortion) - _SPIRV_OP(get_best_ipe_chroma_distortion, GetBestIpeChromaDistortion) - _SPIRV_OP(get_packed_ipe_luma_modes, GetPackedIpeLumaModes) - _SPIRV_OP(get_ipe_chroma_mode, GetIpeChromaMode) - _SPIRV_OP(get_packed_skc_luma_count_threshold, GetPackedSkcLumaCountThreshold) - _SPIRV_OP(get_packed_skc_luma_sum_threshold, GetPackedSkcLumaSumThreshold) - _SPIRV_OP(get_inter_raw_sads, GetInterRawSads) -#undef _SPIRV_OP -} typedef SPIRVMap OCLSPIRVSubgroupAVCIntelBuiltinMap; -template <> inline void SPIRVMap::init() { - add("opencl.event_t", OpTypeEvent); - add("opencl.pipe_t", OpTypePipe); - add("opencl.clk_event_t", OpTypeDeviceEvent); - add("opencl.reserve_id_t", OpTypeReserveId); - add("opencl.queue_t", OpTypeQueue); - add("opencl.sampler_t", OpTypeSampler); -} - typedef SPIRVMap LLVMSPIRVAtomicRmwOpCodeMap; -template <> inline void LLVMSPIRVAtomicRmwOpCodeMap::init() { - add(llvm::AtomicRMWInst::Xchg, OpAtomicExchange); - add(llvm::AtomicRMWInst::Add, OpAtomicIAdd); - add(llvm::AtomicRMWInst::Sub, OpAtomicISub); - add(llvm::AtomicRMWInst::And, OpAtomicAnd); - add(llvm::AtomicRMWInst::Or, OpAtomicOr); - add(llvm::AtomicRMWInst::Xor, OpAtomicXor); - add(llvm::AtomicRMWInst::Max, OpAtomicSMax); - add(llvm::AtomicRMWInst::Min, OpAtomicSMin); - add(llvm::AtomicRMWInst::UMax, OpAtomicUMax); - add(llvm::AtomicRMWInst::UMin, OpAtomicUMin); -} } // namespace SPIRV From 68d4c4cc98c4ec50197b5548f943c0bc20a3b9f3 Mon Sep 17 00:00:00 2001 From: nrudenko Date: Thu, 9 Jul 2020 14:51:47 +0300 Subject: [PATCH 766/771] Move SPIRVAllowUnknownIntrinsics option to TranslatorOpts class --- llvm-spirv/include/LLVMSPIRVOpts.h | 13 +++++++++++++ llvm-spirv/lib/SPIRV/SPIRVWriter.cpp | 11 +++-------- llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h | 4 ++++ llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp | 15 +++++++++++++++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/llvm-spirv/include/LLVMSPIRVOpts.h b/llvm-spirv/include/LLVMSPIRVOpts.h index 62831d0c4b6b7..6abbf15eb9bbe 100644 --- a/llvm-spirv/include/LLVMSPIRVOpts.h +++ b/llvm-spirv/include/LLVMSPIRVOpts.h @@ -137,6 +137,15 @@ class TranslatorOpts { FPContractMode getFPContractMode() const { return FPCMode; } + bool isSPIRVAllowUnknownIntrinsicsEnabled() const noexcept { + return SPIRVAllowUnknownIntrinsics; + } + + void + setSPIRVAllowUnknownIntrinsicsEnabled(bool AllowUnknownIntrinsics) noexcept { + SPIRVAllowUnknownIntrinsics = AllowUnknownIntrinsics; + } + private: // Common translation options VersionNumber MaxVersion = VersionNumber::MaximumVersion; @@ -159,6 +168,10 @@ class TranslatorOpts { // - FPContractMode::Fast allows *all* operations to be contracted // for all entry points FPContractMode FPCMode = FPContractMode::On; + + // Unknown LLVM intrinsics will be translated as external function calls in + // SPIR-V + bool SPIRVAllowUnknownIntrinsics = false; }; } // namespace SPIRV diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp index 1161ad5c97dc0..13abcabbc1fa0 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp @@ -92,11 +92,6 @@ using namespace OCLUtil; namespace SPIRV { -cl::opt SPIRVAllowUnknownIntrinsics( - "spirv-allow-unknown-intrinsics", cl::init(false), - cl::desc("Unknown LLVM intrinsics will be translated as external function " - "calls in SPIR-V")); - static void foreachKernelArgMD( MDNode *MD, SPIRVFunction *BF, std::function @@ -509,8 +504,8 @@ SPIRVFunction *LLVMToSPIRV::transFunctionDecl(Function *F) { if (auto BF = getTranslatedValue(F)) return static_cast(BF); - if (F->isIntrinsic() && - (!SPIRVAllowUnknownIntrinsics || isKnownIntrinsic(F->getIntrinsicID()))) { + if (F->isIntrinsic() && (!BM->isSPIRVAllowUnknownIntrinsicsEnabled() || + isKnownIntrinsic(F->getIntrinsicID()))) { // We should not translate LLVM intrinsics as a function assert(none_of(F->user_begin(), F->user_end(), [this](User *U) { return getTranslatedValue(U); }) && @@ -2131,7 +2126,7 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II, // change is pending the trap/abort intrisinc implementation. return nullptr; default: - if (SPIRVAllowUnknownIntrinsics) + if (BM->isSPIRVAllowUnknownIntrinsicsEnabled()) return BM->addCallInst( transFunctionDecl(II->getCalledFunction()), transArguments(II, BB, diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h index a4ec3ef3b7140..24620bb97085a 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVModule.h @@ -476,6 +476,10 @@ class SPIRVModule { return TranslationOpts.getFPContractMode(); } + bool isSPIRVAllowUnknownIntrinsicsEnabled() const noexcept { + return TranslationOpts.isSPIRVAllowUnknownIntrinsicsEnabled(); + } + // I/O functions friend spv_ostream &operator<<(spv_ostream &O, SPIRVModule &M); friend std::istream &operator>>(std::istream &I, SPIRVModule &M); diff --git a/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp b/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp index ce4cd190dda3b..42be0f4f581f2 100644 --- a/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp +++ b/llvm-spirv/tools/llvm-spirv/llvm-spirv.cpp @@ -178,6 +178,11 @@ static cl::opt FPCMode( SPIRV::FPContractMode::Fast, "fast", "allow all operations to be contracted for all entry points"))); +cl::opt SPIRVAllowUnknownIntrinsics( + "spirv-allow-unknown-intrinsics", cl::init(false), + cl::desc("Unknown LLVM intrinsics will be translated as external function " + "calls in SPIR-V")); + static std::string removeExt(const std::string &FileName) { size_t Pos = FileName.find_last_of("."); if (Pos != std::string::npos) @@ -553,6 +558,16 @@ int main(int Ac, char **Av) { return -1; } + if (SPIRVAllowUnknownIntrinsics.getNumOccurrences() != 0) { + if (IsReverse) { + errs() + << "Note: --spirv-allow-unknown-intrinsics option ignored as it only " + "affects translation from LLVM IR to SPIR-V"; + } else { + Opts.setSPIRVAllowUnknownIntrinsicsEnabled(SPIRVAllowUnknownIntrinsics); + } + } + #ifdef _SPIRV_SUPPORT_TEXT_FMT if (ToText && (ToBinary || IsReverse || IsRegularization)) { errs() << "Cannot use -to-text with -to-binary, -r, -s\n"; From d35a1add245c1f3e0ec99f57290d8dde2aef9426 Mon Sep 17 00:00:00 2001 From: nrudenko Date: Thu, 9 Jul 2020 15:28:41 +0300 Subject: [PATCH 767/771] Extend LLVMSPIRVOpts.h interface allowing pass options to spirv passes --- llvm-spirv/include/LLVMSPIRVLib.h | 5 +++++ llvm-spirv/lib/SPIRV/SPIRVWriterPass.cpp | 20 ++++++++++++++++---- llvm-spirv/lib/SPIRV/SPIRVWriterPass.h | 14 +++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/llvm-spirv/include/LLVMSPIRVLib.h b/llvm-spirv/include/LLVMSPIRVLib.h index 3e8a9f0908828..2fe5b3e8720c3 100644 --- a/llvm-spirv/include/LLVMSPIRVLib.h +++ b/llvm-spirv/include/LLVMSPIRVLib.h @@ -215,6 +215,11 @@ ModulePass *createPreprocessMetadata(); /// ostream. ModulePass *createSPIRVWriterPass(std::ostream &Str); +/// Create and return a pass that writes the module to the specified +/// ostream. +ModulePass *createSPIRVWriterPass(std::ostream &Str, + const SPIRV::TranslatorOpts &Opts); + } // namespace llvm #endif // SPIRV_H diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriterPass.cpp b/llvm-spirv/lib/SPIRV/SPIRVWriterPass.cpp index ffd0676045e41..4e211d0567d83 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriterPass.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVWriterPass.cpp @@ -21,23 +21,26 @@ using namespace llvm; PreservedAnalyses SPIRVWriterPass::run(Module &M) { // FIXME: at the moment LLVM/SPIR-V translation errors are ignored. std::string Err; - writeSpirv(&M, OS, Err); + writeSpirv(&M, Opts, OS, Err); return PreservedAnalyses::all(); } namespace { class WriteSPIRVPass : public ModulePass { std::ostream &OS; // std::ostream to print on + SPIRV::TranslatorOpts Opts; + public: static char ID; // Pass identification, replacement for typeid - explicit WriteSPIRVPass(std::ostream &O) : ModulePass(ID), OS(O) {} + WriteSPIRVPass(std::ostream &OS, const SPIRV::TranslatorOpts &Opts) + : ModulePass(ID), OS(OS), Opts(Opts) {} StringRef getPassName() const override { return "SPIRV Writer"; } bool runOnModule(Module &M) override { // FIXME: at the moment LLVM/SPIR-V translation errors are ignored. std::string Err; - writeSpirv(&M, OS, Err); + writeSpirv(&M, Opts, OS, Err); return false; } }; @@ -46,5 +49,14 @@ class WriteSPIRVPass : public ModulePass { char WriteSPIRVPass::ID = 0; ModulePass *llvm::createSPIRVWriterPass(std::ostream &Str) { - return new WriteSPIRVPass(Str); + SPIRV::TranslatorOpts DefaultOpts; + // To preserve old behavior of the translator, let's enable all extensions + // by default in this API + DefaultOpts.enableAllExtensions(); + return createSPIRVWriterPass(Str, DefaultOpts); +} + +ModulePass *llvm::createSPIRVWriterPass(std::ostream &Str, + const SPIRV::TranslatorOpts &Opts) { + return new WriteSPIRVPass(Str, Opts); } diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriterPass.h b/llvm-spirv/lib/SPIRV/SPIRVWriterPass.h index b8005486bbaad..fe80217230be8 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriterPass.h +++ b/llvm-spirv/lib/SPIRV/SPIRVWriterPass.h @@ -15,6 +15,7 @@ #ifndef SPIRV_SPIRVWRITERPASS_H #define SPIRV_SPIRVWRITERPASS_H +#include "LLVMSPIRVOpts.h" #include "llvm/ADT/StringRef.h" namespace llvm { @@ -27,16 +28,27 @@ class PreservedAnalyses; /// manager. ModulePass *createSPIRVWriterPass(std::ostream &Str); +/// \brief Create and return a pass that writes the module to the specified +/// ostream. Note that this pass is designed for use with the legacy pass +/// manager. +ModulePass *createSPIRVWriterPass(std::ostream &Str, + const SPIRV::TranslatorOpts &Opts); + /// \brief Pass for writing a module of IR out to a SPIRV file. /// /// Note that this is intended for use with the new pass manager. To construct /// a pass for the legacy pass manager, use the function above. class SPIRVWriterPass { std::ostream &OS; + SPIRV::TranslatorOpts Opts; public: /// \brief Construct a SPIRV writer pass around a particular output stream. - explicit SPIRVWriterPass(std::ostream &OS) : OS(OS) {} + explicit SPIRVWriterPass(std::ostream &OS) : OS(OS) { + Opts.enableAllExtensions(); + } + SPIRVWriterPass(std::ostream &OS, const SPIRV::TranslatorOpts &Opts) + : OS(OS), Opts(Opts) {} /// \brief Run the SPIRV writer pass, and output the module to the selected /// output stream. From a2d863f30ae60667b5a990f4c0ff859fe7e45ce3 Mon Sep 17 00:00:00 2001 From: Sven van Haastregt Date: Wed, 15 Jul 2020 10:25:56 +0100 Subject: [PATCH 768/771] Drop unused CLVer member Its use was removed in dff07df ("[SPIRV] Fix assertion due to duplicate operands in opencl version metadata. This happens when two SPIR modules are linked together. Remove check for OCL version in OCLTypeToSPIRV. Only check if language is C or C++.", 2015-12-16). --- llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.cpp | 3 +-- llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.cpp b/llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.cpp index 1c60fa8af22a7..bb1f47d9129c6 100644 --- a/llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.cpp +++ b/llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.cpp @@ -58,8 +58,7 @@ namespace SPIRV { char OCLTypeToSPIRV::ID = 0; -OCLTypeToSPIRV::OCLTypeToSPIRV() - : ModulePass(ID), M(nullptr), Ctx(nullptr), CLVer(0) { +OCLTypeToSPIRV::OCLTypeToSPIRV() : ModulePass(ID), M(nullptr), Ctx(nullptr) { initializeOCLTypeToSPIRVPass(*PassRegistry::getPassRegistry()); } diff --git a/llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.h b/llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.h index 30025cd2aba1f..00d3104d0e780 100644 --- a/llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.h +++ b/llvm-spirv/lib/SPIRV/OCLTypeToSPIRV.h @@ -71,7 +71,6 @@ class OCLTypeToSPIRV : public ModulePass { private: Module *M; LLVMContext *Ctx; - unsigned CLVer; std::map AdaptedTy; // Adapted types for values std::set WorkSet; // Functions to be adapted From 326f12dbb6f78b847073569e146bcd2c7ab081fa Mon Sep 17 00:00:00 2001 From: Dmitry Sidorov Date: Mon, 13 Jul 2020 19:30:25 +0300 Subject: [PATCH 769/771] Fix type mapping for pointers with Device/HostOnlyINTEL storage classes a7b763b265d introduces a bug, when it could be possible to map a single pointer type in LLVM IR to two different pointer types in SPIR-V (when SPV_INTEL_usm_storage_classes extension is not allowed). This patch fixes this bug. Signed-off-by: Dmitry Sidorov --- llvm-spirv/lib/SPIRV/SPIRVWriter.cpp | 7 +++++-- llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h | 12 +++--------- llvm-spirv/test/transcoding/intel_usm_addrspaces.ll | 9 +++++---- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp index 13abcabbc1fa0..26c5ea77cc165 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp @@ -308,8 +308,11 @@ SPIRVType *LLVMToSPIRV::transType(Type *T) { // extension if (!BM->isAllowedToUseExtension( ExtensionID::SPV_INTEL_usm_storage_classes) && - ((AddrSpc == SPIRAS_GlobalDevice) || (AddrSpc == SPIRAS_GlobalHost))) - AddrSpc = SPIRAS_Global; + ((AddrSpc == SPIRAS_GlobalDevice) || (AddrSpc == SPIRAS_GlobalHost))) { + auto NewType = + PointerType::get(T->getPointerElementType(), SPIRAS_Global); + return mapType(T, transType(NewType)); + } if (ST && !ST->isSized()) { Op OpCode; StringRef STName = ST->getName(); diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h index 4ea503613854f..60a9bcc3de60e 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h @@ -538,15 +538,9 @@ class SPIRVStore : public SPIRVInstruction, public SPIRVMemoryAccess { SPIRVInstruction::validate(); if (getSrc()->isForward() || getDst()->isForward()) return; -#ifndef NDEBUG - if (getValueType(PtrId)->getPointerElementType() != getValueType(ValId)) { - assert(getValueType(PtrId) - ->getPointerElementType() - ->getPointerStorageClass() == - getValueType(ValId)->getPointerStorageClass() && - "Inconsistent operand types"); - } -#endif // NDEBUG + assert(getValueType(PtrId)->getPointerElementType() == + getValueType(ValId) && + "Inconsistent operand types"); } private: diff --git a/llvm-spirv/test/transcoding/intel_usm_addrspaces.ll b/llvm-spirv/test/transcoding/intel_usm_addrspaces.ll index 457222be9c372..98a40601e6e73 100644 --- a/llvm-spirv/test/transcoding/intel_usm_addrspaces.ll +++ b/llvm-spirv/test/transcoding/intel_usm_addrspaces.ll @@ -23,10 +23,11 @@ ; CHECK-SPIRV: Name [[HOST_ARG2:[0-9]+]] "arg_host.addr" ; CHECK-SPIRV-EXT: TypePointer [[DEVICE_TY:[0-9]+]] 5936 {{[0-9]+}} ; CHECK-SPIRV-EXT: TypePointer [[HOST_TY:[0-9]+]] 5937 {{[0-9]+}} -; CHECK-SPIRV-NO-EXT: TypePointer [[DEVICE_TY:[0-9]+]] 5 {{[0-9]+}} -; CHECK-SPIRV-NO-EXT: TypePointer [[HOST_TY:[0-9]+]] 5 {{[0-9]+}} -; CHECK-SPIRV: Load [[DEVICE_TY]] {{[0-9]+}} [[DEVICE]] {{[0-9]+}} {{[0-9]+}} -; CHECK-SPIRV: Load [[HOST_TY]] {{[0-9]+}} [[HOST]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV-NO-EXT: TypePointer [[GLOB_TY:[0-9]+]] 5 {{[0-9]+}} +; CHECK-SPIRV-EXT: Load [[DEVICE_TY]] {{[0-9]+}} [[DEVICE]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV-EXT: Load [[HOST_TY]] {{[0-9]+}} [[HOST]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV-NO-EXT: Load [[GLOB_TY]] {{[0-9]+}} [[DEVICE]] {{[0-9]+}} {{[0-9]+}} +; CHECK-SPIRV-NO-EXT: Load [[GLOB_TY]] {{[0-9]+}} [[HOST]] {{[0-9]+}} {{[0-9]+}} ; ModuleID = 'intel_usm_addrspaces.cpp' source_filename = "intel_usm_addrspaces.cpp" From 6f47dbdddddf052dd4f320fc680e24ea5322f2d0 Mon Sep 17 00:00:00 2001 From: nrudenko Date: Thu, 9 Jul 2020 16:42:01 +0300 Subject: [PATCH 770/771] Add SIMTCallINTEL decoration of SPV_INTEL_vector_compute extension Extension is published at https://github.com/intel/llvm/pull/1612 --- llvm-spirv/lib/SPIRV/SPIRVReader.cpp | 4 +++ llvm-spirv/lib/SPIRV/SPIRVWriter.cpp | 8 +++++ llvm-spirv/lib/SPIRV/VectorComputeUtil.h | 1 + llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h | 1 + .../lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h | 1 + .../lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h | 1 + llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp | 1 + .../test/transcoding/decoration_simt_call.ll | 35 +++++++++++++++++++ 8 files changed, 52 insertions(+) create mode 100755 llvm-spirv/test/transcoding/decoration_simt_call.ll diff --git a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp index ca90e1bbcb98a..bd6317c9bdfb1 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVReader.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVReader.cpp @@ -3460,6 +3460,10 @@ bool SPIRVToLLVM::transVectorComputeMetadata(SPIRVFunction *BF) { return true; F->addFnAttr(kVCMetadata::VCFunction); + SPIRVWord SIMTMode = 0; + if (BF->hasDecorate(DecorationSIMTCallINTEL, 0, &SIMTMode)) + F->addFnAttr(kVCMetadata::VCSIMTCall, std::to_string(SIMTMode)); + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { auto ArgNo = I->getArgNo(); diff --git a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp index 26c5ea77cc165..347111bb34454 100644 --- a/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp +++ b/llvm-spirv/lib/SPIRV/SPIRVWriter.cpp @@ -585,6 +585,14 @@ void LLVMToSPIRV::transVectorComputeMetadata(Function *F) { else return; + if (Attrs.hasFnAttribute(kVCMetadata::VCSIMTCall)) { + SPIRVWord SIMTMode = 0; + Attrs.getAttribute(AttributeList::FunctionIndex, kVCMetadata::VCSIMTCall) + .getValueAsString() + .getAsInteger(0, SIMTMode); + BF->addDecorate(DecorationSIMTCallINTEL, SIMTMode); + } + for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I) { auto ArgNo = I->getArgNo(); diff --git a/llvm-spirv/lib/SPIRV/VectorComputeUtil.h b/llvm-spirv/lib/SPIRV/VectorComputeUtil.h index f215b2dc2df3e..772d682a5e42a 100755 --- a/llvm-spirv/lib/SPIRV/VectorComputeUtil.h +++ b/llvm-spirv/lib/SPIRV/VectorComputeUtil.h @@ -116,6 +116,7 @@ const static char VCSLMSize[] = "VCSLMSize"; const static char VCGlobalVariable[] = "VCGlobalVariable"; const static char VCVolatile[] = "VCVolatile"; const static char VCByteOffset[] = "VCByteOffset"; +const static char VCSIMTCall[] = "VCSIMTCall"; const static char VCArgumentKind[] = "VCArgumentKind"; const static char VCArgumentDesc[] = "VCArgumentDesc"; } // namespace kVCMetadata diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h index 57ce0d3eedc0c..078a6ec426376 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVEnum.h @@ -393,6 +393,7 @@ template <> inline void SPIRVMap::init() { {CapabilityVectorComputeINTEL}); ADD_VEC_INIT(DecorationFuncParamIOKind, {CapabilityVectorComputeINTEL}); ADD_VEC_INIT(DecorationStackCallINTEL, {CapabilityVectorComputeINTEL}); + ADD_VEC_INIT(DecorationSIMTCallINTEL, {CapabilityVectorComputeINTEL}); ADD_VEC_INIT(DecorationFuncParamKindINTEL, {CapabilityVectorComputeINTEL}); ADD_VEC_INIT(DecorationFuncParamDescINTEL, {CapabilityVectorComputeINTEL}); } diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h index a4d23c2d51aa0..2b96e6c298497 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVIsValidEnum.h @@ -431,6 +431,7 @@ inline bool isValid(spv::Decoration V) { case DecorationVectorComputeVariableINTEL: case DecorationGlobalVariableOffsetINTEL: case DecorationFuncParamIOKind: + case DecorationSIMTCallINTEL: return true; default: return false; diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h index 5cff7007899f2..5290bdb9bb5a0 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +++ b/llvm-spirv/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h @@ -371,6 +371,7 @@ template <> inline void SPIRVMap::init() { add(DecorationVectorComputeVariableINTEL, "VectorComputeVariableINTEL"); add(DecorationGlobalVariableOffsetINTEL, "GlobalVariableOffsetINTEL"); add(DecorationFuncParamIOKind, "FuncParamIOKind"); + add(DecorationSIMTCallINTEL, "SIMTCallINTEL"); } SPIRV_DEF_NAMEMAP(Decoration, SPIRVDecorationNameMap) diff --git a/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp b/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp index c6992238452a2..862c45e4f4ae6 100644 --- a/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp +++ b/llvm-spirv/lib/SPIRV/libSPIRV/spirv.hpp @@ -477,6 +477,7 @@ enum Decoration { DecorationRestrictPointerEXT = 5355, DecorationAliasedPointer = 5356, DecorationAliasedPointerEXT = 5356, + DecorationSIMTCallINTEL = 5599, DecorationFuncParamKindINTEL = 9624, DecorationFuncParamDescINTEL = 9625, DecorationReferencedIndirectlyINTEL = 5602, diff --git a/llvm-spirv/test/transcoding/decoration_simt_call.ll b/llvm-spirv/test/transcoding/decoration_simt_call.ll new file mode 100755 index 0000000000000..0bd687ea7897d --- /dev/null +++ b/llvm-spirv/test/transcoding/decoration_simt_call.ll @@ -0,0 +1,35 @@ +; RUN: llvm-as %s -o %t.bc +; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_vector_compute --spirv-allow-unknown-intrinsics +; RUN: llvm-spirv %t.spv -o %t.spt --to-text +; RUN: llvm-spirv -r %t.spv -o %t.bc +; RUN: llvm-dis %t.bc -o %t.ll +; RUN: FileCheck %s --input-file %t.spt -check-prefix=SPV +; RUN: FileCheck %s --input-file %t.ll -check-prefix=LLVM + +; ModuleID = 'slm.bc' +source_filename = "slm.cpp" +target datalayout = "e-p:64:64-i64:64-n8:16:32" +target triple = "spir" + +; LLVM-DAG: @k_rte{{[^#]*}}#[[K_RTE:[0-9]+]] +; LLVM-DAG: attributes #[[K_RTE]]{{.*"VCSIMTCall"="5" }} +; SPV-DAG: EntryPoint 6 [[K_RTE:[0-9]+]] "k_rte" +; SPV-DAG: Decorate [[K_RTE]] SIMTCallINTEL 5 + +@in = internal global <256 x i8> undef, align 256 #0 +declare <256 x i8> @llvm.genx.vload(<256 x i8>* nonnull %aaa) + +; Function Attrs: noinline norecurse nounwind readnone +define dso_local dllexport spir_kernel void @k_rte(i32 %ibuf, i32 %obuf) local_unnamed_addr #1 { +entry: + %gload53 = tail call <256 x i8> @llvm.genx.vload(<256 x i8>* nonnull @in) + ret void +} + +attributes #1 = { noinline norecurse nounwind readnone "VCFunction" "VCSIMTCall"="5" "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.module.flags = !{!0} +!llvm.ident = !{!1} + +!0 = !{i32 1, !"wchar_size", i32 4} +!1 = !{!"clang version 8.0.1"} From 5b18de1a0eff9dcbfef9ce36a99e9991036e425d Mon Sep 17 00:00:00 2001 From: Vladimir Lazarev Date: Mon, 20 Jul 2020 11:03:13 +0300 Subject: [PATCH 771/771] [SYCL] Fix LIT test --- clang/test/CodeGenSYCL/noexcept.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/clang/test/CodeGenSYCL/noexcept.cpp b/clang/test/CodeGenSYCL/noexcept.cpp index c1299229ef92f..816f2c43ebfe2 100644 --- a/clang/test/CodeGenSYCL/noexcept.cpp +++ b/clang/test/CodeGenSYCL/noexcept.cpp @@ -18,15 +18,15 @@ void f3() {} void foo_noexcept() noexcept { // CHECK-DEVICE: call spir_func void @_Z2f1v() - // CHECK-HOST-LIN: invoke void @_Z2f1v() - // CHECK-HOST-WIN: invoke void @"?f1@@YAXXZ"() + // CHECK-HOST-LIN: call void @_Z2f1v() + // CHECK-HOST-WIN: call void @"?f1@@YAXXZ"() f1(); } void foo_throw() throw() { // CHECK-DEVICE: call spir_func void @_Z2f2v() - // CHECK-HOST-LIN: invoke void @_Z2f2v() - // CHECK-HOST-WIN: invoke void @"?f3@@YAXXZ"() + // CHECK-HOST-LIN: call void @_Z2f2v() + // CHECK-HOST-WIN: call void @"?f3@@YAXXZ"() f2(); } @@ -38,14 +38,13 @@ struct A { void foo_cleanup() { A a; // CHECK-DEVICE: call spir_func void @_Z2f3v() - // CHECK-HOST: invoke void @_Z2f3v() + // CHECK-HOST: call void @_Z2f3v() f3(); // CHECK-DEVICE: call spir_func void @_ZN1AD1Ev // Regular + exception cleanup // CHECK-HOST-LIN: call void @_ZN1AD1Ev - // CHECK-HOST-LIN: call void @_ZN1AD1Ev + // CHECK-HOST-LIN: call void @_ZN1AD2Ev // CHECK-HOST-WIN: call void @"??1A@@QEAA@XZ"(%struct.A* %a) - // CHECK-HOST-WIN: call void @"??1A@@QEAA@XZ"(%struct.A* %a) #4 [ "funclet"(token %0) ] } template